在 swift 語言中,經過 ! 和 ? 能夠將對象聲明成 Optional,用於標記這個對象能夠有一個指定值,或 者爲nil。在 OC 中,之前是沒有這樣的功能的,所以咱們在開發中會常常遇到由於某個方法應該返回實例而返回了空致使的崩潰的問題。Nullability 的主要用武之地,就是在這裏,它能夠起到提示開發者作是否爲空的判斷的提示。這一特性在 Xcode6.3 中就已經支持,但在 Xcode7 中又作了一些寫法上的小改動。swift
Xcode7 中,系統的框架中已經支持了 Nullability,以下所示,這是 NSArray 中的兩個屬性,其中 nullable 關鍵字說明了這裏可能返回空的值。數組
若是僅僅是在返回值中給開發者一些提示,可能以爲應用並不大,對開發者最大的幫助是這一特性能夠用於方法的參數中,這樣咱們在調用方法時起到的提示做用,將是很是重要的,越是多人合做的項目,做用也越大。例如如下方法中,咱們在調用函數時,若是傳入了空值,編譯器會給咱們警告。框架
屬性聲明中:ide
方法(函數)參數中:函數
iOS9 的 SDK 中已經徹底兼容使用了這些特性,而且 nonnull 的使用會比 nullable 普遍的多,系統提供了這樣一對宏,咱們在這對宏之間定義的變量都會加上 nonnull 的修飾符,只有咱們特殊聲明 nullable 的才須要手動寫。atom
#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") #define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface NSData (FormData) - (void)q_setHttpHeaderFieldWithRequest:(NSMutableURLRequest *)request fileBoundary:(nullable NSString *)fileBoundary; @end NS_ASSUME_NONNULL_END
Xcode 7 對系統中經常使用的一系列 容器類型 都增長了泛型支持,有了泛型就能夠告訴開發人員容器類中裝的對象是什麼類型的。假如向泛型容器中加入不符合要求類型的對象,編譯器會報警告。僅僅是警告,沒什麼實質的卵用。spa
1.正常的狀況下,數組中存放的是 id對象, 若是取出某個對象,想使用點語法訪問它的屬性,必須先進行強轉..net
2.若是咱們使用泛型的話,能夠限制裏面的內容,若是傳入的不是Person類型的對象,就會有警告指針
給集合類型添加一個泛型的約定。(聲明瞭這樣一個數組後,就比如告訴了編譯器,這個數組中的數據類型都是 NSString 類型的,你強行加入別的也是攔不住的,只是個防君子,不防小人的玩意)code
1.加入一個字符串到數組中,沒有任務問題!
2.加入一個NSNumber到數組中,編譯器就報警告⚠️
3.點語法,取出數組中的元素後,直接能夠用點語法訪問
若是不是泛型數組,沒法用點語法直接訪問,須要先強制類型轉換
Xcode7中系統的類,會帶有 ObjectType
這個單詞,它是一個類型通配符,具體怎麼寫並不重要,也能夠寫成xxx,只是系統中都約定使用了 ObjectType
,你也能夠在本身的類中按本身的喜愛來命名。 ObjectType
是傳入類型的 佔位符,它只能在 @interface 上定義(類聲明、類擴展、Category),這個類型在 @interface 和 @end 區間的做用域有效,能夠把它做爲入參、出參、甚至內部 NSArray 屬性的泛型類型,應該說一切都是符合預期的。:
建立一個類,繼承於NSObject,取名叫MyArray:
.m中就不能用 <Type> 了哦
在ViewDidLoad方法中 寫以下代碼
能夠看到當咱們設置泛型爲<Person *>的時候,編譯器就會提示 Person *
設置爲<NSString *> 時,編譯器就會提示 NSString *
當類支持泛型後,它們的 Type 發生了變化,好比下面三個對象看上去都是 Stack,但實際上屬於三個 Type:
不指定泛型類型的 Stack 能夠 和 任意泛型類型轉化,但指定了泛型類型後,兩個不一樣
類型間是不能夠強轉的,否則編譯器會報警告⚠️ 。
假如你但願主動控制轉化關係,就須要使用泛型的協變性和逆變性修飾符了:
__covariant
- 協變性,子類型能夠強轉到父類型
__contravariant
- 逆變性,父類型能夠強轉到子類型
協變:
效果:NSMutableString 是 NSString 的子類
逆變:
效果:NSString 是 NSMutableString 的父類
解決了一個長期以來的小痛點,拿原來的 UITableView 的這個方法來講:
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier;
使用時前面基本會使用 UITableViewCell 子類型的指針來接收返回值,因此這個 API 爲了讓開發者沒必要每次都蛋疼的寫顯式強轉,把返回值定義成了 id 類型,而這個 API 實際上的意思是返回一個 UITableViewCell 或 UITableViewCell子類 的實例,因而新的 __kindof 關鍵字解決了這個問題:
- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;
既明確代表了返回值,又讓使用者沒必要寫強轉。
再舉個帶泛型的例子,UIView 的 subviews 屬性被修改爲了:
@property (nonatomic, readonly, copy) NSArray<__kindof UIView *> *subviews;
這樣,寫下面的代碼時就沒有任何警告了:(否則你要先強轉成UIButton纔會沒有警告)
UIButton *button = view.subviews.lastObject;