1、回顧_isa指針程序員
以前談到過isa指針,isa指針是一個指向所屬類的指針,它標註着一個實例對象的真實類型。緩存
在Object-C中消息機制是依靠objc_msgSend()
這個函數發送消息,函數
objc_msgSend
含兩個參數:receiver、selector。即:objc_msgSend(receiver, selector);測試
而objc_msgSend經過isa指針,找到實例對象所屬的類,也就找到了其所有父類,以下圖所示:spa
一個方法被調用要通過的真實步驟是這樣的:當我門向一個對象發送消息去調用他的方法時,objc_msgSend會根據該實例對象的isa指針去查找該對象的類,而後去查找該類的disptach table中的selector,若是找不到就會依次向上查找它的父類,並在其父類的dispatch table中查找相應的selector,直到NSObject類。一旦找到該selector,objc_msgSend會根據dispatch table中內存地址去調用該selector。這樣實現message和selector在執行階段的動態綁定。爲了提升這種查找轉發的效率。系統會把全部的selector內存地址和調用過的selector的內存地址緩存起來。而經過類的形式劃分不一樣的緩存區域。每個類的緩存區域會包括本身的selector和繼承自父類的selector,在objc_msgSend去查找disptach table前,會先去檢查該類的緩存。若是緩存命中,就直接調用selecotr。指針
2、瞭解_imp指針code
imp是implementation的縮寫,顧名思義imp指針是指向selector的具體實現的指針。在瞭解IMP指針以前,來探討一個問題,如今需求是在不影響層級結構和儘可能少改動的狀況下,讓項目中全部viewController的ViewDidLoad方法中打印本身的類型。瞭解Runtime的同窗,可能會想到對象
method_exchangeImplementations(Method m1, Method m2)blog
這種方式很輕鬆的實現了我門的需求,可是做爲一個優雅的程序員,就要作優雅的事情。下面就來imp指針。繼承
首先要配置工程
進行以下配置:
配置完成,直接上代碼:
使用imp指針更改方法實現成功。這樣作比上一種方式更加優雅。
接下來探討一下method_exchangeImplementations(Method m1, Method m2)方法的實現原理:
從imp指針的地址打印來看貌似這個方法是將兩個方法的imp指針作了互換。
通過這麼多代碼的測試,最終印證的仍是那句話,imp指針是指向selector具體實現的指針。
附加一下真實imp的具體定義: