http://dangpu.sinaapp.com/?p=119
在Objective-C中,message與方法的真正實現是在執行階段綁定的,而非編譯階段。編譯器會將消息發送轉換成對objc_msgSend方法的調用。
objc_msgSend方法含兩個必要參數:receiver、方法名(即:selector),如:[receiver message]; 將被轉換爲:objc_msgSend(receiver, selector);bjc_msgSend方法也能hold住message的參數,如:objc_msgSend(receiver, selector, arg1, arg2, …);
objc_msgSend方法會做按照順序進行以下操作,以完成動態綁定:
1、查找selector所指代的程序(方法的真正實現)。因爲不同類對同一方法有不同的實現,所以對方法的真正實現的查找依賴於receiver的類
2、調用該實現,並將一系列參數傳遞過去
3、將該實現的返回值作爲自己的返回值,返回之
消息傳遞的關鍵是,編譯器構建每個類和對象時所採用的數據結構。每個類都包含以下兩個必要元素:
1、一個指向父類的指針
2、一個調度表(dispatch table)。該調度表將類的selector與方法的實際內存地址關聯起來
每個對象都有一個指向所屬類的指針isa。通過該指針,對象可以找到它所屬的類,也就找到了其全部父類,如下圖所示:
爲了保證消息發送與執行的效率,系統會將全部selector和使用過的方法的內存地址緩存起來。每個類都有一個獨立的緩存,緩存包含有當前類自己的 selector以及繼承自父類的selector。查找調度表(dispatch table)前,消息發送系統首先檢查receiver對象的緩存。
緩存命中的情況下,消息發送(messaging)比直接調用方法(function call)只慢一點點點點。
關於Selector,什麼 是Selector,Selector就是一個字符串,用來表示一個方法。
在Objective-C中,消息是直到運行的時候才和方法實現綁定的。編譯器會把一個消息表達式,
[receiver message]轉換成一個對消息函數objc_msgSend的調用。該函數有兩個主要參數:消息接收者和消息對應的方法名字——也就是方法選標:objc_msgSend(receiver, selector)
同時接收消息中的任意數目的參數:objc_msgSend(receiver, selector, arg1, arg2, ...)
該消息函數做了動態綁定所需要的一切:
它首先找到選標所對應的方法實現。因爲不同的類對同一方法可能會有不同的實現,所以找到的方法實現依賴於消息接收者的類型。
然後將消息接收者對象(指向消息接收者對象的指針)以及方法中指定的參數傳給找到的方法實現。
最後,將方法實現的返回值作爲該函數的返回值返回。
注意:編譯器將自動插入調用該消息函數的代碼。您無須在代碼中顯示調用該消息函數。