Swift iOS中的Nullability Annotations
今天折腾使用swift开发React Native的插件,遇到一个参数必须标记成nonnull的问题。 用Swift写了个RN简单的模块,遇到了下面的错误: [error][tid:com.facebook.react.CalendarManagerQueue][RCTModuleMethod.m:58] Argument 2 (NSNumber) of CalendarManager.addEvent has unspecified nullability but React requires that all NSNumber arguments are explicitly marked as `nonnull` to ensure compatibility with Android.
解决这个错误,只需要在参数前面加上nonnull就可以了,但是为什么呢? 于是google了一下,发现这是Xcode 6.3的一个新特性,即nullability annotations。 Nullability Annotations我们都知道在swift中,可以使用!和?来表示一个对象是optional的还是non-optional,如view?和view!。而在Objective-C中则没有这一区分,view即可表示这个对象是optional,也可表示是non-optional。这样就会造成一个问题:在Swift与Objective-C混编时,Swift编译器并不知道一个Objective-C对象到底是optional还是non-optional,因此这种情况下编译器会隐式地将Objective-C的对象当成是non-optional。 为了解决这个问题,苹果在Xcode 6.3引入了一个Objective-C的新特性:nullability annotations。这一新特性的核心是两个新的类型注释:__nullable和__nonnull。从字面上我们可以猜到,__nullable表示对象可以是NULL或nil,而__nonnull表示对象不应该为空。当我们不遵循这一规则时,编译器就会给出警告。 我们来看看以下的实例, @interface TestNullabilityClass ()
@property (nonatomic,copy) NSArray * items;
- (id)itemWithName:(NSString * __nonnull)name;
@end
@implementation TestNullabilityClass
- (void)testNullability {
[self itemWithName:nil]; // 编译器警告:Null passed to a callee that requires a non-null argument
}
- (id)itemWithName:(NSString * __nonnull)name {
return nil;
}
@end
不过这只是一个警告,程序还是能编译通过并运行。 事实上,在任何可以使用const关键字的地方都可以使用__nullable和__nonnull,不过这两个关键字仅限于使用在指针类型上。而在方法的声明中,我们还可以使用不带下划线的nullable和nonnull,如下所示
@property (nonatomic,copy,nonnull) NSArray * items; @property (nonatomic,copy) NSArray * __nonnull items; Nonnull区域设置(Audited Regions) 如果需要每个属性或每个方法都去指定nonnull和nullable,是一件非常繁琐的事。苹果为了减轻我们的工作量,专门提供了两个宏:NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END。在这两个宏之间的代码,所有简单指针对象都被假定为nonnull,因此我们只需要去指定那些nullable的指针。如下代码所示: NS_ASSUME_NONNULL_BEGIN
@interface TestNullabilityClass ()
@property (nonatomic,copy) NSArray * items;
- (id)itemWithName:(nullable NSString *)name;
@end
NS_ASSUME_NONNULL_END
在上面的代码中,items属性默认是nonnull的,itemWithName:方法的返回值也是nonnull,而参数是指定为nullable的。 不过,为了安全起见,苹果还制定了几条规则: typedef定义的类型的nullability特性通常依赖于上下文,即使是在Audited Regions中,也不能假定它为nonnull。 因为Nullability Annotations是Xcode 6.3新加入的,所以我们需要考虑之前的老代码。实际上,苹果已以帮我们处理好了这种兼容问题,我们可以安全地使用它们: 老代码仍然能正常工作,即使对nonnull对象使用了nil也没有问题。 参考Nullability and Objective-C (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |