消息轉(zhuǎn)發(fā)機制

RunTime:

1、獲取所有的屬性列表、方法列表、協(xié)議列表

2、方法交換

3、方法攔截調(diào)用,容錯處理

4、動態(tài)添加方法,關(guān)聯(lián)對象分類添加屬性objc_setAssociatedObject

消息查找與消息轉(zhuǎn)發(fā)機制:

1、從緩存方法列表中查找

2、從方法列表中查找

3、從父類指針所指對象中查找

4、一直沒找到,轉(zhuǎn)向攔截調(diào)用, 重定向

5、如果沒有重寫攔截調(diào)用的方法,程序報錯

+(BOOL)resolveClassMethod:(SEL)sel;

+(BOOL)resolveInstanceMethod:(SEL)sel;

//后兩個方法需要轉(zhuǎn)發(fā)到其他的類處理

-(id)forwardingTargetForSelector:(SEL)aSelector;

-(void)forwardInvocation:(NSInvocation *)anInvocation;

-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector? //方法簽名

調(diào)用resolveInstanceMethod:方法 (或?resolveClassMethod:)。允許用戶在此時為該 Class 動態(tài)添加實現(xiàn)。如果有實現(xiàn)了,則調(diào)用并返回YES,那么重新開始objc_msgSend流程。這一次對象會響應(yīng)這個選擇器,一般是因為它已經(jīng)調(diào)用過class_addMethod。如果仍沒實現(xiàn),繼續(xù)下面的動作。

調(diào)用forwardingTargetForSelector:方法,嘗試找到一個能響應(yīng)該消息的對象。如果獲取到,則直接把消息轉(zhuǎn)發(fā)給它,返回非 nil 對象。否則返回 nil ,繼續(xù)下面的動作。注意,這里不要返回 self ,否則會形成死循環(huán)。

調(diào)用methodSignatureForSelector:方法,嘗試獲得一個方法簽名。如果獲取不到,則直接調(diào)用doesNotRecognizeSelector拋出異常。如果能獲取,則返回非nil:創(chuàng)建一個 NSlnvocation 并傳給forwardInvocation:。

調(diào)用forwardInvocation:方法,將第3步獲取到的方法簽名包裝成 Invocation 傳入,如何處理就在這里面了,并返回非nil。

調(diào)用doesNotRecognizeSelector:?,默認的實現(xiàn)是拋出異常。如果第3步?jīng)]能獲得一個方法簽名,執(zhí)行該步驟。

上面前4個方法均是模板方法,開發(fā)者可以override,由 runtime 來調(diào)用。最常見的實現(xiàn)消息轉(zhuǎn)發(fā):就是重寫方法3和4,吞掉一個消息或者代理給其他對象都是沒問題的

也就是說_objc_msgForward在進行消息轉(zhuǎn)發(fā)的過程中會涉及以下這幾個方法:

resolveInstanceMethod:方法 (或?resolveClassMethod:)。

forwardingTargetForSelector:方法

methodSignatureForSelector:方法

forwardInvocation:方法

doesNotRecognizeSelector:?方法

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容