Skip to content

Commit e78967c

Browse files
authored
[objective_c] Add NSNull (#2628)
1 parent 4d1f149 commit e78967c

File tree

8 files changed

+151
-4
lines changed

8 files changed

+151
-4
lines changed

pkgs/ffigen/lib/src/code_generator/objc_built_in_types.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const objCBuiltInInterfaces = {
3636
'NSMutableSet': 'NSMutableSet',
3737
'NSMutableString': 'NSMutableString',
3838
'NSNotification': 'NSNotification',
39+
'NSNull': 'NSNull',
3940
'NSNumber': 'NSNumber',
4041
'NSObject': 'NSObject',
4142
'NSOutputStream': 'NSOutputStream',

pkgs/objective_c/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
- Use ffigen 20.0.0
44
- Fix missing `NSNumber` category includes in iOS and macOS `objective_c.m`
55
files.
6-
- Add `NSBundle` to the bindings.
6+
- Add `NSBundle` and `NSNull` to the bindings.
7+
- Fix a [bug](https://github.com/dart-lang/native/issues/2627) where
8+
`NSMutableDictionary.of` returned a `NSDictionary`.
79

810
## 8.1.0
911

pkgs/objective_c/ffigen_objc.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ objc-interfaces:
5656
- NSMutableSet
5757
- NSMutableString
5858
- NSNotification
59+
- NSNull
5960
- NSNumber
6061
- NSObject
6162
- NSOutputStream

pkgs/objective_c/lib/src/converter.dart

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ ObjCObjectBase _defaultObjCConverter(Object o) =>
1919
/// If [dartObject] is not one of the recognized types, [convertOther] is
2020
/// called. If [convertOther] is not provided, an error is thrown.
2121
ObjCObjectBase toObjCObject(
22-
Object dartObject, {
22+
Object? dartObject, {
2323
ObjCObjectBase Function(Object) convertOther = _defaultObjCConverter,
2424
}) => switch (dartObject) {
25+
null => NSNull.null$(),
2526
ObjCObjectBase() => dartObject,
2627
num() => dartObject.toNSNumber(),
2728
String() => dartObject.toNSString(),
@@ -99,6 +100,20 @@ Object toDartObject(
99100
return convertOther(objCObject);
100101
}
101102

103+
/// Converts a Objective C object to the corresponding Dart object.
104+
///
105+
/// See [toDartObject]. This method will additionally return `null` if passed an
106+
/// `NSNull`.
107+
Object? toNullableDartObject(
108+
ObjCObjectBase objCObject, {
109+
Object Function(ObjCObjectBase) convertOther = _defaultDartConverter,
110+
}) {
111+
if (NSNull.isInstance(objCObject)) {
112+
return null;
113+
}
114+
return toDartObject(objCObject, convertOther: convertOther);
115+
}
116+
102117
extension NSArrayToDartList on NSArray {
103118
List<Object> toDartList({
104119
Object Function(ObjCObjectBase) convertOther = _defaultDartConverter,

pkgs/objective_c/lib/src/objective_c_bindings_exported.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ export 'objective_c_bindings_generated.dart'
116116
NSMutableString$Methods,
117117
NSNotification,
118118
NSNotification$Methods,
119+
NSNull,
120+
NSNull$Methods,
119121
NSNumber,
120122
NSNumber$Methods,
121123
NSNumberCreation,

pkgs/objective_c/lib/src/objective_c_bindings_generated.dart

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11564,7 +11564,7 @@ extension NSMutableData$Methods on NSMutableData {
1156411564
/// NSMutableDictionary
1156511565
class NSMutableDictionary extends NSDictionary {
1156611566
/// Creates a [NSMutableDictionary] from [other].
11567-
static NSDictionary of(Map<NSCopying, objc.ObjCObjectBase> other) =>
11567+
static NSMutableDictionary of(Map<NSCopying, objc.ObjCObjectBase> other) =>
1156811568
NSMutableDictionary.dictionaryWithCapacity(other.length)..addAll(other);
1156911569

1157011570
/// Creates a [NSMutableDictionary] from [entries].
@@ -13880,6 +13880,126 @@ extension NSNotification$Methods on NSNotification {
1388013880
}
1388113881
}
1388213882

13883+
/// NSNull
13884+
class NSNull extends NSObject implements NSCopying, NSSecureCoding {
13885+
NSNull._(
13886+
ffi.Pointer<objc.ObjCObject> pointer, {
13887+
bool retain = false,
13888+
bool release = false,
13889+
}) : super.castFromPointer(pointer, retain: retain, release: release);
13890+
13891+
/// Constructs a [NSNull] that points to the same underlying object as [other].
13892+
NSNull.castFrom(objc.ObjCObjectBase other)
13893+
: this._(other.ref.pointer, retain: true, release: true);
13894+
13895+
/// Constructs a [NSNull] that wraps the given raw object pointer.
13896+
NSNull.castFromPointer(
13897+
ffi.Pointer<objc.ObjCObject> other, {
13898+
bool retain = false,
13899+
bool release = false,
13900+
}) : this._(other, retain: retain, release: release);
13901+
13902+
/// Returns whether [obj] is an instance of [NSNull].
13903+
static bool isInstance(objc.ObjCObjectBase obj) {
13904+
return _objc_msgSend_19nvye5(
13905+
obj.ref.pointer,
13906+
_sel_isKindOfClass_,
13907+
_class_NSNull,
13908+
);
13909+
}
13910+
13911+
/// alloc
13912+
static NSNull alloc() {
13913+
final _ret = _objc_msgSend_151sglz(_class_NSNull, _sel_alloc);
13914+
return NSNull.castFromPointer(_ret, retain: false, release: true);
13915+
}
13916+
13917+
/// allocWithZone:
13918+
static NSNull allocWithZone(ffi.Pointer<NSZone> zone) {
13919+
final _ret = _objc_msgSend_1cwp428(
13920+
_class_NSNull,
13921+
_sel_allocWithZone_,
13922+
zone,
13923+
);
13924+
return NSNull.castFromPointer(_ret, retain: false, release: true);
13925+
}
13926+
13927+
/// new
13928+
static NSNull new$() {
13929+
final _ret = _objc_msgSend_151sglz(_class_NSNull, _sel_new);
13930+
return NSNull.castFromPointer(_ret, retain: false, release: true);
13931+
}
13932+
13933+
/// null
13934+
static NSNull null$() {
13935+
final _ret = _objc_msgSend_151sglz(_class_NSNull, _sel_null);
13936+
return NSNull.castFromPointer(_ret, retain: true, release: true);
13937+
}
13938+
13939+
/// supportsSecureCoding
13940+
static bool getSupportsSecureCoding() {
13941+
return _objc_msgSend_91o635(_class_NSNull, _sel_supportsSecureCoding);
13942+
}
13943+
13944+
/// Returns a new instance of NSNull constructed with the default `new` method.
13945+
factory NSNull() => new$();
13946+
}
13947+
13948+
extension NSNull$Methods on NSNull {
13949+
/// autorelease
13950+
NSNull autorelease() {
13951+
final _ret = _objc_msgSend_151sglz(this.ref.pointer, _sel_autorelease);
13952+
return NSNull.castFromPointer(_ret, retain: true, release: true);
13953+
}
13954+
13955+
/// encodeWithCoder:
13956+
void encodeWithCoder(NSCoder coder) {
13957+
_objc_msgSend_xtuoz7(
13958+
this.ref.pointer,
13959+
_sel_encodeWithCoder_,
13960+
coder.ref.pointer,
13961+
);
13962+
}
13963+
13964+
/// init
13965+
NSNull init() {
13966+
objc.checkOsVersionInternal(
13967+
'NSNull.init',
13968+
iOS: (false, (2, 0, 0)),
13969+
macOS: (false, (10, 0, 0)),
13970+
);
13971+
final _ret = _objc_msgSend_151sglz(
13972+
this.ref.retainAndReturnPointer(),
13973+
_sel_init,
13974+
);
13975+
return NSNull.castFromPointer(_ret, retain: false, release: true);
13976+
}
13977+
13978+
/// initWithCoder:
13979+
NSNull? initWithCoder(NSCoder coder) {
13980+
final _ret = _objc_msgSend_1sotr3r(
13981+
this.ref.retainAndReturnPointer(),
13982+
_sel_initWithCoder_,
13983+
coder.ref.pointer,
13984+
);
13985+
return _ret.address == 0
13986+
? null
13987+
: NSNull.castFromPointer(_ret, retain: false, release: true);
13988+
}
13989+
13990+
/// retain
13991+
NSNull retain() {
13992+
final _ret = _objc_msgSend_151sglz(this.ref.pointer, _sel_retain);
13993+
return NSNull.castFromPointer(_ret, retain: true, release: true);
13994+
}
13995+
13996+
/// self
13997+
NSNull self() {
13998+
final _ret = _objc_msgSend_151sglz(this.ref.pointer, _sel_self);
13999+
return NSNull.castFromPointer(_ret, retain: true, release: true);
14000+
}
14001+
}
14002+
1388314003
/// NSNumber
1388414004
class NSNumber extends NSValue {
1388514005
NSNumber._(
@@ -36253,6 +36373,7 @@ late final _class_NSMutableOrderedSet = objc.getClass("NSMutableOrderedSet");
3625336373
late final _class_NSMutableSet = objc.getClass("NSMutableSet");
3625436374
late final _class_NSMutableString = objc.getClass("NSMutableString");
3625536375
late final _class_NSNotification = objc.getClass("NSNotification");
36376+
late final _class_NSNull = objc.getClass("NSNull");
3625636377
late final _class_NSNumber = objc.getClass("NSNumber");
3625736378
late final _class_NSObject = objc.getClass("NSObject");
3625836379
late final _class_NSOrderedCollectionChange = objc.getClass(
@@ -41752,6 +41873,7 @@ late final _sel_notificationWithName_object_ = objc.registerName(
4175241873
late final _sel_notificationWithName_object_userInfo_ = objc.registerName(
4175341874
"notificationWithName:object:userInfo:",
4175441875
);
41876+
late final _sel_null = objc.registerName("null");
4175541877
late final _sel_numberOfArguments = objc.registerName("numberOfArguments");
4175641878
late final _sel_numberWithBool_ = objc.registerName("numberWithBool:");
4175741879
late final _sel_numberWithChar_ = objc.registerName("numberWithChar:");

pkgs/objective_c/test/converter_test.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ void main() {
2424
final obj = NSObject();
2525
expect(toObjCObject(obj), obj);
2626

27+
// NSNull.null$() is a singleton.
28+
expect(toObjCObject(null), NSNull.null$());
29+
expect(toNullableDartObject(NSNull.null$()), null);
30+
2731
expect(toObjCObject(123), isA<NSNumber>());
2832
expect((toObjCObject(123) as NSNumber).longLongValue, 123);
2933
expect(toDartObject(toObjCObject(123)), isA<int>());

pkgs/objective_c/tool/data/extra_methods.dart.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class NSDictionary with MapBase<NSCopying, objc.ObjCObjectBase> {
153153

154154
class NSMutableDictionary {
155155
/// Creates a [NSMutableDictionary] from [other].
156-
static NSDictionary of(Map<NSCopying, objc.ObjCObjectBase> other) =>
156+
static NSMutableDictionary of(Map<NSCopying, objc.ObjCObjectBase> other) =>
157157
NSMutableDictionary.dictionaryWithCapacity(other.length)..addAll(other);
158158

159159
/// Creates a [NSMutableDictionary] from [entries].

0 commit comments

Comments
 (0)