转自 http://www.jianshu.com/p/0aca839891fe
The nullability qualifiers 空特性 修饰符 是Xcode 6.3 引入的一种修饰符,主要用来修饰一个参数是否 可以为空, 用来 和 swift 过渡兼容。
在swift中,使用 !
和 ?
来表示一个 optional
值是 non
还是 some
, !
表示 optional 值不为空, ?
表示 可能为空,可能不为空。 swift 中 ! ? 的用法 可以看这篇文章: Swift中的问号?和感叹号!
我们可以在 Xcode 的 发布说明里面看到相关的说明。
在iOS9 中 Xcode 6.3 之后,Object-C 引入了 一种 为空性 修饰符,因此Objective-C 现在可以表示参数的 nullability
为空性。 修饰 属性 或者 变量。
为空性修饰符 中的 四种修饰符
nonnull
不为空 nullable
可以为空 null_unspecified
不确定是否为空null_resettable
setter 可以为空, getter 不为空在 OC 里面 我们使用 nonnull
和 nullable
来表示 参数和属性 可以为空 或者 不可以为空。
例如,以下是 OC UITableView APIs 里面的一些 为空性 语句:
-(void)registerNib:(nonnull UINib *)nib forCellReuseIdentifier:
(nonnull NSString *)identifier;
-(nullable UITableViewCell *)cellForRowAtIndexPath:
(nonnull NSIndexPath)indexPath;
@property (nonatomic, readwrite, retain, nullable) UIView *backgroundView;
在 上面的方法参数里面。方法1 identifier 参数不能为空。 方法2 indexPath 参数不能为空。 属性 backgroundView 可以为空。
OC 中的为空性修饰符 与 swift中 optional
类型数据的为空性相似。在 swift 中 使用 ?
表示 可以为空, 使用 !
表示 不为空,
swift 中 对一个 optional 类型
使用 !
不为空修饰 称为 implicitly-unwrapped optionals
(隐式拆包optioanls) 。
swift 中的 non-optional
类似于 OC 的 nonnull-qualified types
,例如( UINib!)。
swift 中的 optional
类似于 OC 的 nullable-qualified types
, 例如 ((e.g., UITableViewCell?))。
swift APIs 中 的 为空性 修饰 语句:
func registerNib(nib: UINib, forCellReuseIdentifier identifier: String)
func cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell?
var backgroundView: UIView?
在以上代码中, UIView 或许为空, UITableViewCell 或许为空
为空性修饰符 可以修饰 所有的指针类型,包括 C指针类型,block 类型,以及C++ 指针类型, 为空性修饰符 修饰 指针类型时 使用双下划线,__nonnull
__nullable
。
例如:在 C api 中 在block中的用法
void enumerateStrings(__nonnull CFStringRef (^ __nullable callback)(void));
callback 返回值 可以为空, CFStringRef函数 返回值不为空,在swift中这样使用
func enumerateStrings(callback: (() -> CFString)?)
我们来总结以下, 为空性修饰符,一共有三种。
__nonnull
nullable
nonnull
nullable
!
?
Type qualifier spelling | Objective-C property/method spelling | Swift view | Meaning |
---|---|---|---|
__nonnull | nonnull | Non_optioanl,如 UINib | 该值永远不会为nil(有一种例外是可能参数传递时传入的消息为空) |
__nullable | nullable | Optional,如 UITAbleViewCell? | 该值可能为nil |
__null_unspecified | null_unspecified | 隐式拆包可选类型 如NSDate! | 不确定该值是否为空(很少用) |
在OC中还提供了一个不为空修饰宏 NS_ASSUME_NONNULL_BEGN
和NS_ASSUME_NONNULL_END
。 在接口中 nullable 的是少数,因此为了防止写一大堆 nonnull,Foundation 还提供了一对宏,包在宏里面的对象默认加 nonnull 不为空修饰符,只需要把 nullable 为空的指出来就行。
如下所示:
NS_ASSUME_NONNULL_BEGIN
// …
-(void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier;
-(nullable UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath)indexPath;
@property (nonatomic, readwrite, retain, nullable) UIView *backgroundView;
// …
NS_ASSUME_NONNULL_END
在以上代码中 参数 nib、identifier、indexPath 虽然没有 添加 为空性修饰,但是在 不空空修饰宏中,因此 为 nonull。 backgroundView 为 nullable。
注意点:
typedef
定义的类型不会继承 nullability
特性, 而是根据上下文选择nullable
或 non-nullable
,所以,就算是在 宏内,typedef定义的类型也不会被当作nonnull。 null_resettable
是用来修饰 属性的, 被 null_resettable
修饰的属性, setter
返回值 修饰符为 nullable
, getter
返回值 修饰符为 nonable
. 也就是说 , setter 可以为空, getter 不能为空, (比如某些属性提供了默认值),此时使用 null_resettable
修饰属性 。
例如,UIView
的 tintColor
属性,当我们没有指定 填充色的时候,使用系统默认的填充色。
@property (nonatomic, retain, null_resettable) UIColor *tintColor;
此 属性变量在 swift API 中 为 隐式解包
var tintColor: UIColor!