/*
什麼是runtime(執行時機制):
*/ objective-c是基於c語言加入了物件導向特性和訊息**機制的動態語言,這意味著它不僅需要乙個編譯器,還需要runtime系統來動態建立類和物件,進行訊息傳送和**。objc 從三種不同的層級上與 runtime 系統進行互動,分別是通過 objective-c 源**,通過 foundation 框架的nsobject類定義的方法,通過對 runtime 函式的直接呼叫。
1.runtime是一套比較底層的純c語言api, 屬於1個c語言庫, 包含了很多底層的c語言api。
2.平時編寫的oc**, 在程式執行過程中, 其實最終都是轉成了runtime的c語言**, runtime算是oc的幕後工作者
/*
runtime的作用:
*/runtime是屬於oc的底層, 可以進行一些非常底層的操作(用oc是無法實現的)。
1.在程式執行過程中, 動態建立乙個類(比如kvo的底層實現)
2.在程式執行過程中, 動態地為某個類新增屬性\方法, 修改屬性值\方法
3.遍歷乙個類的所有成員變數(屬性)\所有方法
* nscoding(歸檔和解檔, 利用runtime遍歷模型物件的所有屬性)
* 字典 --> 模型 (利用runtime遍歷模型物件的所有屬性, 根據屬性名從字典中取出對應的值, 設定到模型的屬性上)
* kvo(利用runtime動態產生乙個類)
* 用於封裝框架(想怎麼改就怎麼改)
/*
runtime資料結構:
*/在objective-c中,使用[receiver message]語法並不會馬上執行receiver物件的message方法的**,而是向receiver傳送一條message訊息,這條訊息可能由receiver來處理,也可能由**給其他物件來處理,也有可能假裝沒有接收到這條訊息而沒有處理。其實[receiver message]被編譯器轉化為:
id objc_msgsend ( id self, sel op, ... );
下面簡單介紹runtime中重要的資料結構:
sel
表示方法選擇器。其實它就是對映到方法的c字串,你可以通過objc編譯器命令@selector()或者runtime系統的sel_registername函式來獲取乙個sel型別的方法選擇器。
id id是通用型別指標,能夠表示任何物件。id其實就是乙個指向objc_object結構體指標,它包含乙個class isa成員,根據isa指標就可以順藤摸瓜找到物件所屬的類。
class
class表示物件所屬的類。可以檢視到class其實就是乙個objc_class結構體指標。在物件導向設計中,一切都是物件,class在設計中本身也是乙個物件。
method
method表示類中的某個方法。其實method就是乙個指向objc_method結構體指標,它儲存了方法名(method_name)、方法型別(method_types)和方法實現(method_imp)等資訊。
ivar
ivar表示類中的例項變數。ivar其實就是乙個指向objc_ivar結構體指標,它包含了變數名(ivar_name)、變數型別(ivar_type)等資訊。
imp
imp本質上就是乙個函式指標,指向方法的實現。當你向某個物件傳送一條資訊,可以由這個函式指標來指定方法的實現,它最終就會執行那段**,這樣可以繞開訊息傳遞階段而去執行另乙個方法實現。
cache
cache主要用來快取。cache其實就是乙個儲存method的鍊錶,主要是為了優化方法呼叫的效能。當呼叫方法時,優先在cache查詢,如果沒有找到,再到methodlists查詢。
/* runtime訊息傳送:
*/前面從objc_msgsend作為入口,逐步深入分析runtime的資料結構,了解每個資料結構的作用和它們之間關係後,我們正式轉入訊息傳送這個正題。
objc_msgsend函式
在前面已經提過,當某個物件使用語法[receiver message]來呼叫某個方法時,其實[receiver message]被編譯器轉化為:
id objc_msgsend ( id self, sel op, ... );
現在讓我們看一下objc_msgsend它具體是如何傳送訊息:
1.首先根據receiver物件的isa指標獲取它對應的class
2.優先在class的cache查詢message方法,如果找不到,再到methodlists查詢
3.如果沒有在methodlists找到,再到super_class查詢
4.一旦找到message這個方法,就執行它實現的imp。
/*
方法解析與訊息**:
*/[receiver message]呼叫方法時,如果在message方法在receiver物件的類繼承體系中沒有找到方法,那怎麼辦?一般情況下,程式在執行時就會crash掉,丟擲 unrecognized selector sent to …類似這樣的異常資訊。但在丟擲異常之前,還有三次機會按以下順序讓你拯救程式。
1.method resolution
2.fast forwarding
3.normal forwarding
/*
三種方法的選擇:
*/runtime提供三種方式來將原來的方法實現代替掉,那該怎樣選擇它們呢?
1.method resolution:由於method resolution不能像訊息**那樣可以交給其他物件來處理,所以只適用於在原來的類中代替掉。
2.fast forwarding:它可以將訊息處理**給其他物件,使用範圍更廣,不只是限於原來的物件。
3.normal forwarding:它跟fast forwarding一樣可以訊息**,但它能通過nsinvocation物件獲取更多訊息傳送的資訊,例如:target、selector、arguments和返回值等資訊。
/*
method swizzling:
*/就是在執行時將乙個方法的實現代替為另乙個方法的實現。如果能夠利用好這個技巧,可以寫出簡潔、有效且維護性更好的**。
總結:雖然在平時專案不是經常用到objective-c的runtime特性,但當你閱讀一些ios開源專案時,你就會發現很多時候都會用到。所以深入理解objective-c的runtime資料結構、訊息**機制有助於你更容易地閱讀和學習開源專案。
runtime 執行時機制
首先,第乙個問題,1 runtime實現的機制是什麼,怎麼用,一般用於幹嘛?這個問題我就不跟大家繞彎子了,直接告訴大家,runtime是一套比較底層的純c語言api,屬於1個c語言庫,包含了很多底層的c語言api。在我們平時編寫的oc 中,程式執行過程時,其實最終都是轉成了runtime的c語言 r...
runtime 執行時機制
必備常識 1.ivar 成員變數 2.method 成員方法相關應用 1.nscoding 歸檔和解檔,利用runtime遍歷模型物件的所有屬性 2.字典 模型 利用runtime遍歷模型物件的所有屬性,根據屬性名從字典中取出對應的值,設定到模型的屬性上 3.kvo 利用runtime動態產生乙個類...
runtime 執行時機制
runtime 執行時機制 一 runtime是什麼 1 runtime是乙個全動態語言,是基於c語言的庫,裡面包含了很多底層的c語言函式。2 平時編寫的oc 在程式執行過程中,其實最終都是轉成了runtime的c語言 runtime算是oc方法的底層實現,換句話說oc的實現也就是runtime的底...