Objective-C消息轉(zhuǎn)發(fā)

OC中調(diào)用方法就是向?qū)ο蟀l(fā)送消息
下面的代碼:

 [self performSelector:@selector(method) withObject:nil];

如果說(shuō)method方法不存在,就會(huì)出現(xiàn):unrecognized selector sent to instance
從發(fā)送消息到崩潰中間經(jīng)歷了什么?
首先分兩種情況
1,如果發(fā)送的是一個(gè)實(shí)例方法,會(huì)經(jīng)過(guò)三個(gè)步驟
第一步:

+ (BOOL)resolveInstanceMethod:(SEL)sel

這個(gè)方法是實(shí)例方法未實(shí)現(xiàn)時(shí)自動(dòng)執(zhí)行,這個(gè)方法里面是讓你在當(dāng)前類里面對(duì)未實(shí)行的方法做彌補(bǔ)

void dynamicMethodIMP(id sel,SEL _cmdd){
    NSLog(@"resolveInstanceMethod調(diào)用成功");
}

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    if (sel == @selector(method)) {
//        class_addMethod([self class],sel,(IMP));
        class_addMethod([self class],sel,(IMP)dynamicMethodIMP, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

第二步:
如果第一步resolveInstanceMethod你沒做處理,便會(huì)來(lái)到這一步,如果你處理了第一步,第二步是不會(huì)執(zhí)行的

- (id)forwardingTargetForSelector:(SEL)aSelector{
    if (aSelector == @selector(method)) {
        return [TestClass new];
    }
    return nil;
}
@implementation TestClass
- (void)method{
    NSLog(@"method");
}
@end

這一步是在其他類里面找對(duì)應(yīng)的方法,所以TestClass里面必須要實(shí)現(xiàn)method方法,不然同樣會(huì)崩潰
第三步:
經(jīng)歷過(guò)第一步,在本類中找彌補(bǔ)方法,第二步,在其他類中找彌補(bǔ)方法后,如果都沒有找到,便會(huì)來(lái)到第三步

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature *methodSignature = [super methodSignatureForSelector:aSelector];
    if (!methodSignature) {
        methodSignature = [NSMethodSignature signatureWithObjCTypes:"v@:*"];
    }
    return methodSignature;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
    testClass *messageForwarding = [testClass new];
    if ([messageForwarding respondsToSelector:anInvocation.selector]) {
        [anInvocation invokeWithTarget:messageForwarding];
    }
}

這一步實(shí)現(xiàn)方法的重新簽名
2.如果是調(diào)用了一個(gè)類方法,該類方法沒有實(shí)現(xiàn)該怎么辦
便會(huì)調(diào)用resolveClassMethod

void dynamicMethodIMP(id sel,SEL _cmdd){
    NSLog(@"resolveInstanceMethod調(diào)用成功");
}
@implementation testObject
+ (BOOL)resolveClassMethod:(SEL)sel{
  if (sel == @selector(hehe1)){
       class_addMethod(objc_getMetaClass("testObject"),sel,(IMP)dynamicMethodIMP, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}
@end

看里面class_addMethod的第一個(gè)參數(shù),是objc_getMetaClass("testObject"),該方法是獲取當(dāng)前類的元類,如果用[self class]是會(huì)崩潰的,因?yàn)閐ynamicMethodIMP是一個(gè)c方法,它是存在于元類里面的MessageList里面的,當(dāng)前類找不到該方法,元類的知識(shí)可以看我另一篇文章:iOS類和元類關(guān)系
如果resolveClassMethod方法沒有實(shí)現(xiàn),就會(huì)直接崩潰,也就是說(shuō)它沒有實(shí)例方法里面的第二步和第三步。
resolveInstanceMethod和methodSignatureForSelector、forwardInvocation只是在實(shí)例方法缺失才會(huì)執(zhí)行,類方法缺失不會(huì)執(zhí)行,這點(diǎn)要注意

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

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

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