當(dāng)我們在查看蘋果iOS各種開發(fā)框架的頭文件時,在屬性和方法的參數(shù)禁谦,方法的返回值的修飾中·經(jīng)常會看到 nullable
胁黑,nonnull
,null_resettable
州泊,null_unspecified
等關(guān)鍵字
其實這幾個關(guān)鍵字是蘋果在Xcode 6.3
引入的一個Objective-C
的新特性:nullability annotations
。在Swift
中可以使用!和?來表示一個對象是optional
的還是non-optional
漂洋,如button?
和button!
遥皂。而在Objective-C
中則沒有這一區(qū)分,button
即可表示這個對象是optional
刽漂,也可表示是non-optioanl
演训。這樣就會造成一個問題:在Swift
與Objective-C
混編時,Swift
編譯器并不知道一個Objective-C
對象到底是optional
還是non-optional
贝咙,因此這種情況下編譯器會隱式地將Objective-C
的對象當(dāng)成是non-optional
样悟。引入nullability annotations
一方面為了讓iOS
程序員平滑地從Objective-C
過渡到Swift
,另一方面也促使開發(fā)者在編寫Objective-C
代碼時更加規(guī)范庭猩,減少同事之間的溝通成本窟她。
一: nonnull
字面意思: 不能為空(可以用來修飾屬性, 或者方法的參數(shù), 方法的返回值)
只能修飾對象,不能修飾基本數(shù)據(jù)類型
代碼:
//三種使用方式都可以
@property (nonatomic, copy, nonnull) NSString *name;
@property (nonatomic, copy) NSString * _Nonnull name;
@property (nonatomic, copy) NSString * __nonnull name;
//補充(不適用于assign屬性蔼水,因為它是專門用來修飾指針的)
@property (nonatomic, assign) NSUInteger age;
//補充(用下面宏包裹起來的屬性全部都具nonnull特征,當(dāng)然震糖,如果其中某個屬性你不希望有這個特征,也可以自己定義趴腋,比如加個nullable)
//在NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END之間,定義的所有對象屬性和方法默認(rèn)都是nonnull
//也可以在定義方法的時候使用
//返回值和參數(shù)都不能為空
- (nonnull NSString *)test:(nonnull NSString *)name;
//同上
- (NSString * _Nonnull)test1:(NSString * _Nonnull)name;
在調(diào)用這些屬性或者方法的時候, 參數(shù)的類型都會帶有nonnull
的提示的
Nonnull
區(qū)域設(shè)置(Audited Regions)
在查看蘋果iOS各種開發(fā)框架的頭文件時吊说,我們發(fā)現(xiàn)都是用nullable
修飾的屬性和方法,為什么都沒看到nonnull
修飾的屬性和方法呢优炬?
事實上颁井,如果需要每個屬性或每個方法的參數(shù)和返回值都去指定nonnull
和nullable
,是一件非常繁瑣的事蠢护。蘋果為了減輕我們的工作量雅宾,專門提供了兩個宏:NS_ASSUME_NONNULL_BEGIN
和NS_ASSUME_NONNULL_END
。蘋果用NS_ASSUME_NONNULL_BEGIN
糊余,NS_ASSUME_NONNULL_END
這兩個宏來統(tǒng)一給屬性和方法參數(shù)和返回值加上nonnull
修飾秀又,NS_ASSUME_NONNULL_BEGIN
和 NS_ASSUME_NONNULL_END
之間,定義的所有對象屬性和方法默認(rèn)都是nonnull
贬芥。如UIButton
的頭文件吐辙,下圖所示:
??:
NS_ASSUME_NONNULL_BEGIN
- (NSString *)buyPen:( NSString *)book;
NS_ASSUME_NONNULL_END
不過,為了安全起見蘸劈,蘋果還制定了幾條規(guī)則:
-
typedef
定義的類型的nullability
特性通常依賴于上下文昏苏,即使是在Audited Regions
中,也不能假定它為nonnull
。 - 復(fù)雜的指針類型(如
id *
)必須顯示去指定是nonnull
還是nullable
贤惯。例如洼专,指定一個指向nullable
對象的nonnull
指針,可以使用”__nullable id * __nonnull
”孵构。 - 我們經(jīng)常使用的
NSError **
通常是被假定為一個指向nullable NSError
對象的nullable
指針屁商。
二: nullable
字面意思: 可以為空 (使用方法和上面幾乎一樣, 但是好像沒有上面類似的宏)
只能修飾對象,不能修飾基本數(shù)據(jù)類型
//三種使用方式
// 方式一:
@property (nonatomic, copy, nullable) NSString *name;
// 方式二:
@property (nonatomic, copy) NSString *_Nullable name;
// 方式三:
@property (nonatomic, copy) NSString *__nullable name;
三: null_resettable
get:不能返回空, set可以為空(注意:如果使用null_resettable,必須 重寫get方法或者set方法,處理傳遞的值為空的情況)
@property (nonatomic, copy, null_resettable) NSString *name;
- (void)setName:(NSString *)name {
if (name == nil) {
name = @"XXX";
}
_name = name;
}
- (NSString *)name {
if (_name == nil) {
_name = @"XXX";
}
return _name;
}
四: _Null_unspecified
不確定是否為空
// 方式一:
@property(nonatomic, strong) NSNumber *_Null_unspecified height;
// 方式二:
@property(nonatomic, strong) NSNumber *__null_unspecified height;
// 方式三:
@property(nonatomic, strong, null_unspecified) NSNumber * height;