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