Nonnull区域设置(Audited Regions)
如果需要每个属性或每个方法都去指定nonnull和nullable,是一件非常繁琐的事。苹果为了减轻我们的工作量,专门提供了两个宏:NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END。
在
#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
#define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
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。
复杂的指针类型(如id *)必须显示去指定是nonnull还是nullable。例如,指定一个指向nullable对象的nonnull指针,可以使用”__nullable id * __nonnull”。
我们经常使用的NSError **通常是被假定为一个指向nullable NSError对象的nullable指针。
NS_ASSUME_NONNULL_BEGIN & NS_ASSUME_NONNULL_END
从表面意思来看,NS设定不可为空开始 & NS设定不可为空结束
苹果提供的两个宏,方便我们在定义属性的时候将不可为空的属性都写在 “NS设定不可为空开始” 和 “NS设定不可为空结束”之间,默认写在这之间的属性是不可为空的。
所有简单指针都被假定设为非空(nonnull),因此我们只需要去指定那些可为空的(nullable)的指针,这样不用麻烦的去将每个属性或方法都去指定nonnull和nullable,减轻了开发的工作量。
在Xcode升级到10.0 beta4版本后,创建类时系统自动会添加这两个宏:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nullable ,nonatomic, assign) int age;
@end
NS_ASSUME_NONNULL_END
其中NS_ASSUME_NONNULL_BEGIN 和 NS_ASSUME_NONNULL_END在Xcode10.0 beat4版本自动添加。
name 不可为空
age 可为空
创建person对象,给属性赋值:
Person *p = [[Person alloc] init];
p.name = nil;
p.age = nil;
给name给空,系统会提醒:
image.png
image.png