天天看點

iOS - OC 語言新特性前言1、可選類型檢測2、泛型3、類型延拓符

相對于 Java,OC 語言是一門古老的語言了,而它又是一門不斷發展完善的語言。一些新的編譯特性,為 OC 語言帶來了許多新的活力。在 Xcode7 中,iOS9 的 SDK 已經全面相容了 Objective-C 的一些新特 性和新功能。這些功能都隻作用于編譯期,對程式的運作并沒有影響,是以,它可以很好的向下進行相容,無縫的銜接低版本的 iOS 系統,如果可以将這些新特性都應用于開發,開發效率和代碼品質,相比之前會有一個很大的提升。

在 swift 語言中,通過 ! 和 ? 可以将對象聲明成 Optional,用于在開發中标記這個對象是否可以為空。在 OC 中,以前是沒有這樣的功能的,是以我們在開發中會經常遇到因為某個函數應該傳回執行個體而傳回了空導緻的崩潰。Nullability 的主要用武之地,就是在這裡,它可以起到提示開發者做是否為空的判斷的提示。這一特性在 Xcode6.3 中就已經支援,但在 Xcode7 中又做了一些寫法上的小改動。

Xcode7 中,系統的架構中已經支援了 Nullability,如下所示,這是 NSArray 中的兩個屬性,其中 nullable 關鍵字說明了這裡可能傳回空的值。

如果僅僅是在傳回值中給開發者一些提示,可能覺得應用并不大,對開發者最大的幫助是這一特性可以用于函數的參數中,這樣我們在調用函數時起到的提示作用,将是非常重要的,越是多人合作的項目,作用也越大。例如以下方法中,我們在調用函數時,如果傳入了空值,編譯器會給我們警告。

修飾參數:

屬性聲明中:

方法(函數)參數中:

iOS9 的 SDK 中已經完全相容使用了這些特性,并且 nonnull 的使用會比 nullable 廣泛的多,系統提供了這樣一對宏,我們在這對宏之間定義的變量都會加上 nonnull 的修飾符,隻有我們特殊聲明 nullable 的才需要手動寫。

Xcode 7 對系統中常用的一系列容器類型都增加了泛型支援(),有了泛型後就可以指定容器類中對象的類型了。假如向泛型容器中加入錯誤的對象,編譯器會報警告。

泛型聲明格式:在聲明類的時候,在類型後面

泛型定義格式:放在限制的類型後面

泛型好處:

1、提高程式員開發規範,一看就知道是什麼類型。

2、限制類型,不允許傳入其他的類型。

3、從集合中取出來,直接可以使用點文法。

泛型開發中使用場景:

1、一般都是用來限制集合類型。

泛型不定義就是 id。

泛型定義是獨立,隻能修飾目前對象。

疑問:誰才能使用泛型?隻要聲明了泛型的類,才能定義。

自定義泛型:

開發中使用場景:當聲明一個類,有個屬性不确定類型,當建立對象的時候才确定這個屬性是什麼類型的時候,就才可以采取使用泛型。

在 Xcode7 中,我們可以給集合類型添加一個泛型的約定,如下,聲明了這樣一個數組後,就好比告訴了編譯器,這個數組中的資料類型都是 NSString 類型的。

如果用這個數組中元素的方法,會出現如下提示。使用點文法可以通路到數組中泛型的方法了。

iOS - OC 語言新特性前言1、可選類型檢測2、泛型3、類型延拓符

在我們向這個數組中追加元素的時候,編譯器将元素的類型提示了出來,并且将 FromArray 方法中需要的元素類型也提示了出來。

iOS - OC 語言新特性前言1、可選類型檢測2、泛型3、類型延拓符

同樣,如果我們向這個數組中追加類型不比對的元素,如下,編譯器會給我們一個警告。

iOS - OC 語言新特性前言1、可選類型檢測2、泛型3、類型延拓符

觀察 Xcode7 中 iOS 系統的類,我們可以發現這麼一個好玩的東西:ObjectType。它既不是一個類型,也不是關鍵字,然而卻大量存在,如下是系統的 NSMutableArray 的頭檔案。這個 ObjectType 其實隻是一個類型辨別符,它具體怎麼寫并不重要,隻是系統中都約定使用了 ObjectType,你也可以在自己的類中按自己的喜好來命名。

建立一個類,繼承于 NSObject,取名叫 MyArray:

我們在使用這個自定義的集合類型時,就會有和系統一樣的效果了:

iOS - OC 語言新特性前言1、可選類型檢測2、泛型3、類型延拓符

多參數的泛型集合,有一個非常好的例子,就是 NSDictionary,在 Xcode7 中我們可以這樣寫字典。可以看到,字典鍵值的類型編譯器為我們提示了出來,結合上面類型通配符的使用,對于多參的集合,将參數類型用 “,” 隔開即可。

iOS - OC 語言新特性前言1、可選類型檢測2、泛型3、類型延拓符

因為有了泛型集合的概念,相比之前,我們的類型實際上更加複雜了,比如還拿我們自定義的集合類型來舉例,array 和 muArray 在編譯器看來已經是不同的類型,如果我們強行轉換,會報如下的警告:

iOS - OC 語言新特性前言1、可選類型檢測2、泛型3、類型延拓符

是以,就有了逆變和協變這個概念,不指定泛型類型的對象可以和任意泛型類型轉化,但指定了泛型類型後,兩個不同類型間是不可以強轉的,假如你希望主動控制轉化關系,就需要使用泛型的協變性和逆變性修飾符。

上面的情況,我們将自定義的類做如下修改,就不會出現警告:

NSMutableString 是 NSString 的子類,在 MyArray 定義中加入了 __covariant 可以進行轉換。但将 <code>MyArray&lt;NSString *&gt;</code> 轉換為 <code>MyArray&lt;NSMutableString *&gt;</code> 時仍會報警告。

iOS - OC 語言新特性前言1、可選類型檢測2、泛型3、類型延拓符

在開發中,開發者經常會遇到這樣的情況,例如通過 tag 擷取某些 UI 控件時,viewWithTag 方法通常會傳回給我們一個 UIView 類型的指針,這就需要開發者手動的強轉一下,十分麻煩。新增加的 __kindof 修飾符可以幫助我們解除這個煩惱。

建立一個自定義的數組對象,并向其中添加一個 UIButton,我們會看到有如下一個警告:

iOS - OC 語言新特性前言1、可選類型檢測2、泛型3、類型延拓符

這也是我們開發中常遇到的問題,以前需要強轉。但是以後就不需要了,我們在聲明這個數組時加上一個 __kindof 修飾符。警告就消失了,這個修飾符就是告訴編譯器,這裡可以傳回 UIView 的子類指針。

<code>id,instancetype,__kindof</code> 作為傳回值時的比較: