NS_ASSUME_NONNULL_BEGIN
和NS_ASSUME_NONNULL_END
在.h文件中,能够看到这两个宏,翻看定义,这两个宏的代码是css
#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") #define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
知识普及:html
说到这两个宏就须要引伸出Swift和Objective-C的差别。在Swift中有一个明显的区别就是optional reference,比方说NSView
和NSView?
.可是在OC中就都只能是NSView *
类型。由于Swift编译器并不能肯定NSView *
是否为optional类型,因此在Swift中,会被隐式解包为NSView!
.ios
所以OC添加了_Nullable
和_Nonnull
这两种类型注释。swift
比方说下面的代码:安全
@interface AAPLList : NSObject <NSCoding, NSCopying> // ... - (AAPLListItem * _Nullable)itemWithName:(NSString * _Nonnull)name; @property (copy, readonly) NSArray * _Nonnull allItems; // ... @end // -------------- [self.list itemWithName:nil]; // warning!
声明了一个非空的形参,返回值为可空的方法和一个非空的属性。app
另外,也能够这样使用(注意两种用法的区别,第一种是放在类型后面,须要添加下划线。第二种是在类型以前)ide
- (nullable AAPLListItem *)itemWithName:(nonnull NSString *)name; - (NSInteger)indexOfItem:(nonnull AAPLListItem *)item; @property (copy, nullable) NSString *name; @property (copy, readonly, nonnull) NSArray *allItems;
回到两个宏定义上:使用NS_ASSUME_NONNULL_BEGIN
和NS_ASSUME_NONNULL_END
能够代表全部的指针类型都为nonnull.ui
NS_ASSUME_NONNULL_BEGIN @interface Student: NSObject @property (nonatomic, copy) NSString *name; - (nullable Student*)studentWithName:(NSString *)name; @end NS_ASSUME_NONNULL_END Student *s = [self studentWithName: nil]; // warning self.name = nil; // warning
出于安全考虑,这条规则有几个例外:atom
typedef
类型通常没有内在的可空性——它们要么为空,要么非空,根据具体的取值而定。所以,即便在审核区内,typedef
类型也不会默认为nonnull
。id *
,必须显式使用注解。例如,指明一个非空的指针指向可空的对象引用,要用__nullable id * __nonnull
。NSError **
通常用来在方法参数中返回错误信息,所以它老是默认为可空的指针指向可空的NSError
引用。这方面的更多信息能够参考Error Handling Programming Guide。spa