你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> Runtime初涉之消息轉發

Runtime初涉之消息轉發

編輯:IOS開發基礎

上一篇文章咱們提到了Runtime的消息傳遞機制,主要圍繞三個C語言API來展開進行的。這篇文章我將從另外三個方法來描述Runtime中另一個特性:消息轉發機制。

一、消息轉發機制

當向某個對象發送一條消息時,若該對象的方法列表以及它相應繼承鏈上的方法列表都無法找到以該消息選擇子作為key的方法實現時,則會觸發消息轉發機制。

1、動態方法解析

+ (BOOL)resolveInstanceMethod:(SEL)sel;

首先,當接受到未能識別的選擇子時,運行時系統會調用該函數用以給對象一次機會來添加相應的方法實現,如果用戶在該函數中動態添加了相應方法的實現,則跳轉到方法的實現部分,並將該實現存入緩存中,以供下次調用。

2、備援接收者

- (id)forwardingTargetForSelector:(SEL)aSelector;

如果運行時在消息轉發的第一步中未找到所調用方法的實現,那麼當前接收者還有第二次機會進行未知選擇子的處理。這時運行期系統會調用上述方法,並將未知選擇子作為參數傳入,該方法可以返回一個能處理該選擇子的對象,運行時系統會根據返回的對象進行查找,若找到則跳轉到相應方法的實現,則消息轉發結束。

3、完整的消息轉發

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

當運行時系統檢測到第二步中用戶未返回能處理相應選擇子的對象時,那麼來到這一步就要啟動完整的消息轉發機制了。該方法可以改變消息調用目標,運行時系統根據所改變的調用目標,向調用目標方法列表中查詢對應方法的實現並實現跳轉,這種方式和第二步的操作非常相似。當然你也可以修改方法的選擇子,亦或者向所調用方法中追加一個參數等來跳轉到相關方法的實現。

最後,如果消息轉發的第三步還未能處理該未知選擇子的話,那麼最終會調用NSObject類的如下方法用以異常的拋出,表明該選擇子最終未能處理。

- (void)doesNotRecognizeSelector:(SEL)aSelector;

下面附上完整的消息轉發流程圖:

691078-9049faadbcbbeac9.png

二、消息轉發驗證

好了,看了那麼多的理論知識,相比大家也已經累了,那我們用一個實例來具體說明Runtime的消息轉發機制吧。我是傳送門~~~

首先新建一個工程,並在工程中添加Cat、Dog and Chicken三個類,並在每個類的.h文件中聲明jump方法,在Cat.m文件中聲明消息轉發的第一步方法:resolveInstanceMethod: ,在該方法中動態添加jump方法的實現。

691078-007d020324759b96.jpg
消息轉發第一步

注:在第一步中動態添加方法實現用到了Runtime中的class_addMethod方法,該方法用以向該類的實例對象中添加相應的方法實現。

然後在main.m文件中調用Cat實例的jump方法,就會看到在控制台打印出如下結果:

691078-f4540ec5bef526c2.jpg
消息轉發第一步打印結果

然後在Dog.m文件中驗證消息轉發第二步過程,為了讓運行時系統能夠運行到forwardingTargetForSelector:方法,我們先在resolveInstanceMethod:中返回NO,代碼如下:

202.jpg
消息轉發第二步

然後按照之前的樣子,在main.m文件中讓Dog也jump起來,運行之後打印結果如下:

203.jpg
消息轉發第二步打印結果

最後我們來驗證消息轉發第三步驟的過程。

在最後的Chicken.m文件中我們讓前兩步的方法分別返回NO和nil值,用以快速觸發消息轉發機制中的完整消息轉發機制。在驗證這一步中我們注意到,在調用forwardInvocation:方法之前我們需要實現methodSignatureForSelector:方法,並將相應選擇子的描述返回。

204.jpg
消息轉發第三步

這裡我用了改變調用目標這種方式進行消息轉發機制,至於改換選擇子,讀者可以自行嘗試運行哈,具體我已在項目代碼中寫明,最終調用Chicken實例的jump方法,其打印結果如下:
205.jpg

消息轉發第三步打印結果

明明分別調用了三個動物的jump,最後在控制台只看到了Cat一直在jump。。。

如果有覺得上述我講的不對的地方歡迎指出,大家多多交流溝通。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved