背景介绍
在
Swift
中,我们会使用?
和!
去显式声明一个对象或者方法的参数是optional
还是non-optional
,而在Objective-C
中则没有这一区分,这样就会带来一个问题:在Swift
与Objective-C
混编时,Swift
编译器并不知道一个Objective-C
对象或者一个方法的参数到底是optional
还是non-optional
,因此这种情况下编译器会隐式地都当成是non-optional
来处理,这显然是不太好的
发展历程
为了解决这个问题,苹果在
Xcode 6.3
引入了一个Objective-C
的新特性:Nullability Annotations
,这一新特性的核心是两个新的类型修饰:__nullable
和__nonnull
。从字面上我们可知,__nullable
表示对象可以是NULL
或nil
,而__nonnull
表示对象不应该为空。当我们不遵循这一规则时,编译器就会给出警告。
在 Xcode 7 中,为了避免与第三方库潜在的冲突(猜测),苹果把__nonnull/__nullable
改成_Nonnull/_Nullable
。再加上苹果同样支持了没有下划线的写法nonnull/nullable
,于是就造成现在有三种写法这样混乱的局面。但是这三种写法本质上都是互通的,只是放的位置不同
null_resettable
作用:setter可为空, gette不可为空
应用实例
方法返回值的修饰
- (nullable NSString*)method;
- (NSString* __nullable)method;
- (NSString* _Nullable)method;
声明属性的修饰
@property (nonatomic,copy,nullable) NSString *aString;
@property (nonatomic,copy) NSString* __nullable aString;
@property (nonatomic,copy) NSString* _Nullable aString;
方法参数的修饰
- (void)methodWithString:(nullable NSString*)aString;
- (void)methodWithString:(NSString* _Nullable)aString;
- (void)methodWithString:(NSString* __nullable)aString;
**而对于双指针类型对象
、 Block
的返回值 、 Block
的参数 等,这时候就不能用 nonnull/nullable
修饰,只能用带下划线的 __nonnull/__nullable
或者 _Nonnull/_Nullable
- (void)methodWithError:(NSError* _Nullable * _Nullable)error
- (void)methodWithError:(NSError* __nullable* __null_unspecified)error;
// 以及其他的组合方式
- (void)methodWithBlock:(nullablevo id(^)())block;
// 注意上面的 nullable 用于修饰方法传入的参数 Block 可以为空,而不是修饰 Block 返回值;
- (void)methodWithBlock:(void(^ _Nullable)())block;
- (void)methodWithBlock:(void(^ __nullable)())block;
- (void)methodWithBlock:(nullableid__nonnull(^)(id__nullableparams))block;
// 注意上面的 nullable 用于修饰方法传入的参数 Block 可以为空,而 __nonnull 用于修饰 Block 返回值 id 不能为空;
- (void)methodWithBlock:(id__nonnull(^ __nullable)(id__nullableparams))block;
- (void)methodWithBlock:(id_Nonnull (^ _Nullable)(id_Nullable params))block;
// the method accepts a nullable block that returns a nonnull value
// there are some more combinations here, you get the idea
网友评论