iOS NS_ASSUME_NONNULL_BEGIN __nullable __nonnull 使用

__nullable和__nonnull是Xcode 6.3引入的新的关键字。

顾名思义,__nullable表示可以为nil,__nonnull则反之。


举例代码如下:

@implementation ViewController


- (void)viewDidLoad {

    [superviewDidLoad];

    [selfsetName:nil];//会产生警告;

}


- (void)setName:(NSString * __nonnull)name {

    NSLog(@"%@",name);

}


@end


__nullable也可以写成nullable,__nonnull也可以写成nonnull,但是位置不同。写法如下:

- (void)setName:(nonnullNSString * )name {

    NSLog(@"%@",name);

}


如果按照下面的方式写,会报错。

- (void)setName:(NSString *nonnull)name {

    NSLog(@"%@",name);

}




也可以修饰属性,如下:

@interfaceViewController ()


@property (strong,nonatomic,nonnull)NSString *name1;

@property (strong,nonatomic,__nonnull)NSString *name2;

@property (__nonnull,strong,nonatomic)NSString *name3;

@property (nonnull,strong,nonatomic)NSString *name4;

@property (strong,nonatomic)NSString * __nonnull name5;


@end



但如下的写法,是错误的:

@property (strong,nonatomic)NSString * nonnull name6;

@property (strong,nonatomic)nonnull NSString *name7;


然后说下 NS_ASSUME_NONNULL_BEGIN    NS_ASSUME_NONNULL_END


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指针。


你可能感兴趣的:(iOS基础库学习)