OC 消息轉發機制

當一個對象沒法接收某一消息時,就會啓動所謂「消息轉發(message forwarding)」機制,經過這一機制,咱們能夠告訴對象如何處理未知的消息。默認狀況下,對象接收到未知的消息,會致使程序崩潰,經過控制檯,咱們能夠看到如下異常信息:函數

這段異常信息其實是由NSObject的「doesNotRecognizeSelector」方法拋出的。不過,咱們能夠採起一些措施,讓咱們的程序執行特定的邏輯,而避免程序的崩潰。spa

消息轉發機制基本上分爲三個步驟:code

1>、動態方法解析
2>、備用接收者
3>、完整轉發
消息的轉發流程圖:對象

 

Snip20160501_5.pngip

動態方法解析

對象在接收到未知的消息時,首先會調用所屬類的類方法
+resolveInstanceMethod:(實例方法)或者
+resolveClassMethod:(類方法)。get

在這個方法中,咱們有機會爲該未知消息新增一個「處理方法」,經過運行時class_addMethod函數動態添加到類裏面就能夠了。it

這種方案更多的是爲了實現@dynamic屬性。io

備用接收者

- (id)forwardingTargetForSelector:(SEL)aSelector

若是在上一步沒法處理消息,則Runtime會繼續調如下方法:
若是一個對象實現了這個方法,並返回一個非nil的結果,則這個對象會做爲消息的新接收者,且消息會被分發到這個對象。固然這個對象不能是self自身,不然就是出現無限循環。固然,若是咱們沒有指定相應的對象來處理aSelector,則應該調用父類的實現來返回結果。class

這一步合適於咱們只想將消息轉發到另外一個能處理該消息的對象上。但這一步沒法對消息進行處理,如操做消息的參數和返回值。test

完整消息轉發

若是在上一步還不能處理未知消息,則惟一能作的就是啓用完整的消息轉發機制了。
咱們首先要經過,指定方法簽名,若返回nil,則表示不處理。
以下代碼:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
   if ([NSStringFromSelector(aSelector) isEqualToString:@"testInstanceMethod"]){
     return [NSMethodSignature signatureWithObjcTypes:"v@:"];
  }  
return [super methodSignatureForSelector: aSelector];
}

若返回方法簽名,則會進入下一步調用如下方法,對象會建立一個表示消息的NSInvocation對象,把與還沒有處理的消息有關的所有細節都封裝在anInvocation中,包括selector,目標(target)和參數。
咱們能夠在forwardInvocation方法中選擇將消息轉發給其它對象。咱們能夠經過anInvocation對象作不少處理,好比修改實現方法,修改響應對象等.
以下所示:

- (void)forwardInvovation:(NSInvocation)anInvocation
{
    [anInvocation invokeWithTarget:_helper];
    [anInvocation setSelector:@selector(run)];
    [anInvocation invokeWithTarget:self];
}

 

做者:玩運營規則的男人 連接:https://www.jianshu.com/p/adf0d566c887 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

相關文章
相關標籤/搜索