假設我們在
Objective C 中向一個對象發送它無法處理的消息,會出現什麼情況呢?我們知道發送消息是通過
objc_send(id, SEL, ...) 來實作的,它會首先在對象的類對象的 cache,method list 以及父類對象的 cache,
method list 中依次查找 SEL 相應的 IMP;這個是須要對類對象的結構熟悉,不清楚的能夠參考我的下一篇文章》,假設沒有找到且實作了動态方法決議機制就會進行決議,假設沒有實作動态方法決議機制或決議失敗且實作了消息轉發機制就會進入消息轉發流程,否則程式
crash。也就是說假設同一時候提供了動态方法決議和消息轉發,那麼動态方法決議先于消息轉發,僅僅有當動态方法決議依舊無法正确決議
selector 的實作,才會嘗試進行消息轉發。
1. 什麼是動态方法決議
Objective
C 提供了一種名為動态方法決議的手段,使得我們能夠在執行時動态地為一個 selector 提供實作。我們僅僅要實作
+resolveInstanceMethod: 或 +resolveClassMethod: 方法,并在當中為指定的 selector 提供實作就可以(通過調用執行時函數 class_addMethod
來加入?)。這兩個方法都是 NSObject 中的類方法,其原型為:
2.消息轉發
實作下面這兩個方法
從上面的示範樣例示範能夠看出,動态方法決議是先于消息轉發的。
假設向一個
Objective C 對象對象發送它無法處理的消息(selector),那麼編譯器會依照例如以下次序進行處理:
1,首先看是否為該 selector
提供了動态方法決議機制,假設提供了則轉到 2;假設沒有提供則轉到 3;
2,假設動态方法決議真正為該 selector
提供了實作,那麼就調用該實作,完畢消息發送流程,消息轉發就不會進行了;假設沒有提供,則轉到 3;
3,其次看是否為該 selector
提供了消息轉發機制,假設提供了消息了則進行消息轉發,此時,不管消息轉發是如何實作的,程式均不會
crash。(由于消息調用的控制權全然交給消息轉發機制處理,即使消息轉發并沒有做不論什麼事情,執行也不會有錯誤,編譯器更不會有錯誤提示。);假設沒提供消息轉發機制,則轉到
4;
4,執行報錯:無法識别的
selector,程式 crash;
參考: