在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方法會做按照順序進行以下操作,以完成動態綁定:每個對象都有一個指向所屬類的指針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)只慢一點點點點。 參考資料: