轉自:http://my.oschina.net/amoyai/blog/94561
在Objective-C中,message與方法的真正實現是在執行階段綁定的,而非編譯階段。編譯器會將消息發送轉換成對objc_msgSend方法的調用。
? ? objc_msgSend方法含兩個必要參數:receiver、方法名(即:selector),如:
? ?
[receiver message];
將被轉換為:
objc_msgSend(receiver, selector);
?
? ? objc_msgSend方法也能hold住message的參數,如:
? ? objc_msgSend(receiver, selector, arg1, arg2, …);
??
? ? objc_msgSend方法會做按照順序進行以下操作,以完成動態綁定:
- 查找selector所指代的程序(方法的真正實現)。因為不同類對同一方法有不同的實現,所以對方法的真正實現的查找依賴于receiver的類
- 調用該實現,并將一系列參數傳遞過去
- 將該實現的返回值作為自己的返回值,返回之
? ? 消息傳遞的關鍵是,編譯器構建每個類和對象時所采用的數據結構。每個類都包含以下兩個必要元素:
- 一個指向父類的指針
- 一個調度表(dispatch table)。該調度表將類的selector與方法的實際內存地址關聯起來
?
? ? 每個對象都有一個指向所屬類的指針
isa
。通過該指針,對象可以找到它所屬的類,也就找到了其全部父類,如下圖所示:
?
? ? 當向一個對象發送消息時,objc_msgSend方法根據對象的
isa
指針找到對象的類,然后在類的調度表(dispatch table)中查找selector。如果無法找到selector,objc_msgSend通過指向父類的指針找到父類,并在父類的調度表(dispatch table)中查找selector,以此類推直到
NSObject
類。一旦查找到selector,objc_msgSend方法根據調度表的內存地址調用該實現。
通過這種方式,message與方法的真正實現在執行階段才綁定。
?
? ? 為了保證消息發送與執行的效率,系統會將全部selector和使用過的方法的內存地址緩存起來。每個類都有一個獨立的緩存,緩存包含有當前類自己的 selector以及繼承自父類的selector。查找調度表(dispatch table)前,消息發送系統首先檢查receiver對象的緩存。
? 緩存命中的情況下,消息發送(messaging)比直接調用方法(function call)只慢一點點點點。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
