深入Objective C的動態特性

2021-06-27 20:21:51 字數 3457 閱讀 2365

目錄(?)

[-]

動態語言基礎

深入執行時

objective-c有相當多的動態特性,基本上也是最常用的有動態型別(dynamic typing)、動態繫結(dynamic binding)和動態載入(dynamic loading),這些都是在cocoa程式開發中非常常用的語言特性,在此之後oc底層也提供了相當豐富的執行時特性,比如列舉類屬性方法、獲取方法實現等等。雖然在平常的cocoa開發中這些底層的執行特性基本用不著,但是在某些情況下如果你知道這些特性並合理加以運用的話,往往能事半功倍。

1.動態型別

也就是執行時再決定物件的型別。這類動態特性在日常應用中非常常見,簡單的說就是id型別。id型別即通用的物件類,任何物件都可以被id指標指向,而在實際應用中往往使用introspection(內省)來確定該物件實際所屬類:

id obj = someinstance;//

id指標指向了obj物件

if ([obj iskindofclass:someclass])//

採用內省來判斷這個obj物件的確切型別也可以使用ismemberofclass方法(nsobject方法)

2.動態繫結

基於動態型別,在某個例項物件被確定後,其型別便被確定了。該物件對應的屬性和相應訊息也被完全確定了,這就是動態繫結的實質。在繼續之前,需要明確objective-c中的訊息機制。由於oc的動態特性,oc中很少提及"函式"的概念,傳統的函式一般在編譯時就已經把引數資訊和函式實現打包到編譯後的原始碼中了。而在oc中最常使用的是訊息機制。呼叫乙個例項的方法,所做的是向該例項的指標傳送訊息,例項在接收到訊息之後,從自身的實現中尋找響應這條訊息的方法。

動態繫結所做的,即是在例項所屬的類確定後,將某些屬性和相應的方法繫結到例項上。這裡所指的屬性和方法當然包括了原來沒有在類中實現的,而是在執行時才需要的新加入的實現。在cocoa層次上,我們一般會向乙個nsobject物件傳送-respondtoselector:或者-instancesrespondtoselector:來確定物件是否可以對某個sel做出相應,而在oc**訊息機制被觸發之前,對應的類的+resolveclassmethod:和+resolveinstancemethod:將會被呼叫,在此時有機會動態地向類或者例項新增新的方法,也就是類的實現是可以動態繫結的。

3.動態載入

根據需求載入所需的資源,對於ios開發來說基本就是根據不同的機型來適配。最經典的例子就是在retina裝置上載入@2x的,而在老一些的普通屏裝置上載入原圖。

基本的動態特性在常規的cocoa開發中非常常用,特別是動態型別和動態繫結。由於cocoa程式大量地使用protocol-delegate的設計模式,因此大部分的delegate指標型別必須是id,以滿足執行時delegate的動態替換。而oc中還有一些高階或者說更加底層的執行時特性,在一般的cocoa開發中較為少見,基本被運用在oc和其他語言的介面上。但是如果有所了解並且使用得當的話,在cocoa中往往可以輕易解決棘手的問題。

這類執行時特性大多由/usr/lib/libobjc.a.dylib這個動態庫提供,裡面包括對類、例項成員、成員方法和訊息傳送的很多的api,包括獲取類例項變數列表,替換類中方法,為類成員新增變數,動態改變方法實現等等,十分強大。雖然文件開頭表明是對於mac os x objective-c 2.0適用,但是由於這些是oc的底層方法,因此對於ios開發來說也是完全相同的。

舉乙個簡單的例子。比如在進行universal應用或者遊戲時,如果使用ib構建大量的自定義的ui,那麼iphone版本轉向ipad版本的過程中面臨的一

個重要問題就是如何從不同的nib中載入介面。在ios5以前,所有的uiviewcontroller在使用預設的頁面載入時(init 或者initwithnibname:),都會走

-loadnibnamed:owner:options:。而因為我們無法拿到-loadnibnamed:owner:options:的實現,因此對其過載是比較困難而且存在風險的。因此在做ipad版本的nib時,乙個簡單的辦法是將所有的nib的命名方式統一,然後使用自己實現的新的類似-loadnibnamed:owner:options:的方法將原方法替換掉,同時保證非ipad的裝置還走原來的loadnibnamed:owner:options:方法。使用oc執行時特性可以較簡單地完成這一任務。

**如下,在程式執行時呼叫+swizze,交換自己實現的loadnibnamed:owner:options:和系統的loadnibnamed:owner:options:,之後所有的loadnibnamed:owner:options:訊息都將會發為loadnibnamed:owner:options:,由自己的**進行處理。

12

3

4

5

6

+(bool)swizze

method newmethod = class_getinstancemethod(self,@selector(loadpadnibnamed:owner:options:));//取出自定義的實現方法,儲存為newmethod

1

if(!newmethod) method_exchangeimplementations(oldmethod, newmethod);returnyes; }//用自定義的方法實現來取代系統的方法實現

loadnibnamed:owner:options

的實現如下,注意在其中的

loadnibnamed:owner:options

由於之前已經進行了交換,因此實際會傳送為系統的loadnibnamed:own

1

2

3

4

5

6

7

8

9

10

11

12

13

-(nsarray*)loadpadnibnamed:(nsstring*)name owner:(id)owner options:(nsdictionary*)optionselse

}

深入理解Objective c中 class的含義

原文 來自 在objective c中,當乙個類需要引用另乙個類,即建立復合關係的時候,需要在類的標頭檔案中建立被引用類的指標。如 car.h 實現類我們先省略,如果你直接這麼編譯,編譯器會報錯,告訴你它不知道tire和engine是什麼。這時候有兩個選擇,乙個是import這兩個被引用類的標頭檔案...

深入理解Objective c中 class的含義

在objective c中,當乙個類需要引用另乙個類,即建立復合關係的時候,需要在類的標頭檔案中建立被引用類的指標。如 car.h 實現類我們先省略,如果你直接這麼編譯,編譯器會報錯,告訴你它不知道tire和engine是什麼。這時候有兩個選擇,乙個是import這兩個被引用類的標頭檔案,另乙個是使...

深入理解Objective c中 class的含義

在objective c中,當乙個類需要引用另乙個類,即建立復合關係的時候,需要在類的標頭檔案中建立被引用類的指標。如 car.h import inte ce car 實現類我們先省略,如果你直接這麼編譯,編譯器會報錯,告訴你它不知道tire和engine是什麼。這時候有兩個選擇,乙個是impor...