1.NS_ASSUME_NONNULL_BEGIN && NS_ASSUME_NONNULL_END
在Swift
中存在Option
類型疼进,也就是使用碉京?和僵芹!聲明的變量瀑志。但是OC里面沒(méi)有這個(gè)特征,因?yàn)樵赬CODE6.3之后出現(xiàn)新的關(guān)鍵詞定義用于OC轉(zhuǎn)SWIFT時(shí)候可以區(qū)分到底是什么類型
__nullable
&& ___nonnull
__nullable
指代對(duì)象可以為NULL或者為NIL
__nonnull
指代對(duì)象不能為null
當(dāng)我們不遵循這一規(guī)則時(shí),編譯器就會(huì)給出警告脖阵。
我們來(lái)看看以下的實(shí)例,
@interface TestNullabilityClass ()
@property (nonatomic, copy) NSArray * items;
- (id)itemWithName:(NSString * __nonnull)name;
@end
@implementation TestNullabilityClass
...
- (void)testNullability {
[self itemWithName:nil]; // 編譯器警告:Null passed to a callee that requires a non-null argument
}
- (id)itemWithName:(NSString * __nonnull)name {
return nil;
}
@end
事實(shí)上墅茉,在任何可以使用const
關(guān)鍵字的地方都可以使用__nullable
和__nonnull
命黔,不過(guò)這兩個(gè)關(guān)鍵字僅限于使用在指針類型上呜呐。而在方法的聲明中,我們還可以使用不帶下劃線的nullable
和nonnull
悍募,如下所示:
- (nullable id)itemWithName:(NSString * nonnull)name
在屬性聲明中蘑辑,也增加了兩個(gè)相應(yīng)的特性,因此上例中的items屬性可以如下聲明:
@property (nonatomic, copy, nonnull) NSArray * items;
當(dāng)然也可以用以下這種方式:
@property (nonatomic, copy) NSArray * __nonnull items;
推薦使用nonnul
l這種方式坠宴,這樣可以讓屬性聲明看起來(lái)更清晰洋魂。
Non null
區(qū)域設(shè)置(Audited Regions)
如果需要每個(gè)屬性或每個(gè)方法都去指定nonnull
和nullable
,是一件非常繁瑣的事喜鼓。蘋(píng)果為了減輕我們的工作量副砍,專門提供了兩個(gè)宏:NS_ASSUME_NONNULL_BEGIN
和NS_ASSUME_NONNULL_END
。在這兩個(gè)宏之間的代碼庄岖,所有簡(jiǎn)單指針對(duì)象都被假定為nonnull豁翎,因此我們只需要去指定那些nullable的指針。如下代碼所示:
NS_ASSUME_NONNULL_BEGIN
@interface TestNullabilityClass ()
@property (nonatomic, copy) NSArray * items;
- (id)itemWithName:(nullable NSString *)name;
@end
NS_ASSUME_NONNULL_END
在上面的代碼中隅忿,items屬性默認(rèn)是non null
的心剥,itemWithName:方法的返回值也是non null
,而參數(shù)是指定為nullable
的背桐。
不過(guò)优烧,為了安全起見(jiàn),蘋(píng)果還制定了幾條規(guī)則:
typedef定義的類型的nullability特性通常依賴于上下文链峭,即使是在Audited Regions中畦娄,也不能假定它為nonnulla
。
復(fù)雜的指針類型(如id *)必須顯示去指定是nonnull
還是nullable
熏版。例如纷责,指定一個(gè)指向nullable
對(duì)象的nonnull
指針,可以使用”
__nullable id * __nonnull
我們經(jīng)常使用的NSError **
通常是被假定為一個(gè)指向nullable NSError
對(duì)象的nullable指針撼短。
兼容性
因?yàn)镹ullability Annotations是Xcode 6.3新加入的再膳,所以我們需要考慮之前的老代碼。實(shí)際上曲横,蘋(píng)果已以幫我們處理好了這種兼容問(wèn)題喂柒,我們可以安全地使用它們:
老代碼仍然能正常工作, 即使對(duì)nonnull
對(duì)象使用了nil也沒(méi)有問(wèn)題禾嫉。
老代碼在需要和swift混編時(shí)灾杰,在新的swift編譯器下會(huì)給出一個(gè)警告。
nonnull
不會(huì)影響性能熙参。事實(shí)上艳吠,我們?nèi)匀豢梢栽谶\(yùn)行時(shí)去判斷我們的對(duì)象是否為nil
。
事實(shí)上孽椰,我們可以將nonnull/nullable
與我們的斷言和異常一起看待昭娩,其需要處理的問(wèn)題都是同一個(gè):違反約定是一個(gè)程序員的錯(cuò)誤凛篙。特別是,返回值是我們可控的東西栏渺,如果返回值是nonnull
的呛梆,則我們不應(yīng)該返回nil
,除非是為了向后兼容磕诊。
NS_ENUM_AVAILABLE_IOS
從單詞的字面可以看出使用這個(gè)宏說(shuō)明這個(gè)枚舉開(kāi)始IOS的版本
IOS版本如下 7_0 代表7.0的版本.用_替換
參數(shù)只有一個(gè)NS_ENUM_AVAILABLE_IOS(2_0) 代表>=2.0開(kāi)始
NS_ENUM_DEPRECATED_IOS
代表枚舉類型已經(jīng)過(guò)時(shí)的API 第一個(gè)參數(shù)是開(kāi)始的時(shí)候填物,第二個(gè)參數(shù)是過(guò)時(shí)的時(shí)候
NS_ENUM_DEPRECATED_IOS(2_0,7_0) 代表開(kāi)始于IOS2.0廢棄于IOS7.0 也就是>=2.0 <=7.0
__TVOS_PROHIBITED
代表這個(gè)枚舉或者類,方法霎终,參數(shù)在TVOS系統(tǒng)上面不能使用
typedef NS_ENUM(NSInteger, UIStatusBarStyle) {
UIStatusBarStyleDefault = 0, // Dark content, for use on light backgrounds
UIStatusBarStyleLightContent NS_ENUM_AVAILABLE_IOS(7_0) = 1, // Light content, for use on dark backgrounds
UIStatusBarStyleBlackTranslucent NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 1,
UIStatusBarStyleBlackOpaque NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 2,
} __TVOS_PROHIBITED;
UIKIT_EXTERN
extern
這個(gè)是定義字符串 變量 比#define
更加的高效 .但是UIKIT_EXTERN是根據(jù)是否是C語(yǔ)言宏定義滞磺,根據(jù)語(yǔ)言區(qū)分 ,比extern更加的高效
例子
UIKIT_EXTERN NSString *const UIApplicationInvalidInterfaceOrientationException NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
上面的代碼一般定義在.H 在.M實(shí)現(xiàn) 實(shí)現(xiàn)要去掉UIKIT_EXTERN.代表IOS6.0之后可以用神僵,在TVOS系統(tǒng)不可用雁刷。
NS_CLASS_AVAILABLE_IOS
代表類開(kāi)始的API 和上面說(shuō)的類似
例子
NS_CLASS_AVAILABLE_IOS(2_0) @interface UIApplication : UIResponder
NS_EXTENSION_UNAVAILABLE_IOS
標(biāo)記IOS插件不能使用這些API,后面有一個(gè)參數(shù),可以作為提示保礼,用什么API替換
例子
+ (UIApplication *)sharedApplication NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.");
__kindof
可以參考下面的連接 我就不多啰嗦了
Xcode 7新的特性Lightweight Generics 輕量級(jí)泛型與__kindof修飾符
NS_REQUIRES_SUPER
字面上必須繼承父類的方法(有待考證)
SDK_HIDE_TIDE
暫定 沒(méi)查到干什么的 字面上是在SDK隱藏
NS_DESIGNATED_INITIALIZER
用來(lái)定義一些初始化方法只能過(guò)來(lái)這些標(biāo)記的初始化