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

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

1、動態(tài)方法解析

對象在收到無法處理的消息時,會調(diào)用下面的方法,前者是調(diào)用類方法時會調(diào)用,后者是調(diào)用對象方法時會調(diào)用。

// 類方法專用

+ (BOOL)resolveClassMethod:(SEL)sel

// 對象方法專用

+ (BOOL)resolveInstanceMethod:(SEL)sel

在該方法中,需要給對象所屬類動態(tài)的添加一個方法,并返回YES,表明可以處理

void dynamicMethodIMP(id self, SEL _cmd) { ? ?

????NSLog(@" >> dynamicMethodIMP");

}

+ (BOOL)resolveInstanceMethod:(SEL)sel { ? ?

????NSLog(@"%@", NSStringFromSelector(sel)); ? ?

????if (sel == @selector(run)) { ? ? ? ?

????????class_addMethod([self class], sel, (IMP)dynamicMethodIMP, "v@:"); ? ? ? ?

????????return YES; ? ?

? ? ? ?} ? ?

????return [super resolveInstanceMethod:sel];

}

2、備援接受者

經(jīng)歷了第一步后,如果該消息還是無法處理,那么就會調(diào)用下面的方法,查詢是否有其它對象能夠處理該消息。

- (id)forwardingTargetForSelector:(SEL)aSelector

在這個方法里,我們需要返回一個能夠處理該消息的對象

- (id)forwardingTargetForSelector:(SEL)aSelector { ? ?

????NSLog(@"%@", NSStringFromSelector(aSelector)); ? ?

????if (aSelector == @selector(run)) { ? ? ? ?

????????Animal *animal = [[Animal alloc] init]; ? ? ? ?

????????return animal; ? ?

????} ? ?

????return [super forwardingTargetForSelector:aSelector];

}

3、完整的消息轉(zhuǎn)發(fā)

經(jīng)歷了前兩步,還是無法處理消息,那么就會做最后的嘗試,先調(diào)用methodSignatureForSelector:獲取方法簽名,然后再調(diào)用forwardInvocation:進行處理,這一步的處理可以直接轉(zhuǎn)發(fā)給其它對象,即和第二步的效果等效,但是很少有人這么干,因為消息處理越靠后,就表示處理消息的成本越大,性能的開銷就越大。所以,在這種方式下,會改變消息內(nèi)容,比如增加參數(shù),改變選擇子等等。

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector

- (void)forwardInvocation:(NSInvocation *)anInvocation

下面是改變選擇子的例子

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { ? ? ????NSLog(@"%@", NSStringFromSelector(aSelector)); ? ?

????if (aSelector == @selector(run)) { ? ? ? ?

????????NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:"v@:"]; ? ? ? ?

????????return signature; ? ?

????} ? ?

????return [super methodSignatureForSelector:aSelector];

}

- (void)forwardInvocation:(NSInvocation *)anInvocation { ? ?

????NSLog(@"%@", anInvocation); ? ?

????NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:"v@:"]; ? ? ????anInvocation = [NSInvocation invocationWithMethodSignature:signature]; ? ?

????[anInvocation setSelector:@selector(runNew)]; ? ?

????????if ([self respondsToSelector:@selector(runNew)]) { ? ? ? ?

????????[anInvocation invokeWithTarget:self]; ? ? ? ?

????????return; ? ?

????} else { ? ? ? ?

????????Animal *s = [[Animal alloc] init]; ? ? ? ?

? ? ? ?if ([s respondsToSelector:anInvocation.selector]) { ? ? ? ? ? ?

????????????[anInvocation invokeWithTarget:s]; ? ? ? ? ? ?

????????????return; ? ? ? ?

????????} ? ?

????} ? ?

????[super forwardInvocation:anInvocation];

}

- (void)runNew { ? ?

????NSLog(@"runNewrunNewrunNew");

}

最后編輯于
?著作權(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ù)。

相關(guān)閱讀更多精彩內(nèi)容

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