美文网首页
434,利用OC对象的消息重定向forwardingTarget

434,利用OC对象的消息重定向forwardingTarget

作者: 枫叶1234 | 来源:发表于2021-01-26 11:19 被阅读0次

    在OC中,当像一个对象发送消息,而对象找到消息后,从它的类方法列表,父类方法列表,一直找到根类方法列表都没有找到与这个选择子对应的函数指针。那么这个对象就会触发消息转发机制。

    OC对象的继承链和isa指针链如图:
    image.png
    消息转发流程如下:

    1.先调用实例方法resolveInstanceMethod
    如果作者在这里使用runtime动态添加对应的方法,并且返回yes。就万事大吉。对象找到了处理的方法,
    并且将这个新增的方法添加到类的方法缓存列表
    2.如果上面的方法返回NO的话,对象会调用forwardingTargetForSelector方法
    允许作者选择其他的对象,处理这个消息。
    这个方法,也是待会我们要做文章的地方。画重点。
    3.如果上面两个方法都没有做处理,那么对象会执行最后一个方法methodSignatureForSelector,提供一个有效的方法签名,若提供了有效的方法签名,程序将会通过forwardInvocation方法执行签名。若没有提供方法签名就会触发doesNotRecognizeSelector方法,触发崩溃。

    整个调用流程图如下:
    image.png
    整个代码调用顺序如下:
    //1
    + (BOOL)resolveClassMethod:(SEL)sel {
        NSLog(@"1---%@",NSStringFromSelector(sel));
        NSLog(@"1---%@",NSStringFromSelector(_cmd));
        return NO;
    }
    + (BOOL)resolveInstanceMethod:(SEL)sel {
        NSLog(@"1---%@",NSStringFromSelector(sel));
        NSLog(@"1---%@",NSStringFromSelector(_cmd));
        return NO;
    }
    //2
    - (id)forwardingTargetForSelector:(SEL)aSelector {
        NSLog(@"2---%@",NSStringFromSelector(aSelector));
        NSLog(@"2---%@",NSStringFromSelector(_cmd));
        return nil;
    }
    //3.最后一步,返回方法签名
    -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
        NSLog(@"3---%@",NSStringFromSelector(aSelector));
        NSLog(@"3---%@",NSStringFromSelector(_cmd));
        if ([NSStringFromSelector(aSelector) isEqualToString:@"gogogo"]) {
            return [[UnknownModel2 new] methodSignatureForSelector:aSelector];
        }
        return [super methodSignatureForSelector:aSelector];
    }
    //3.1处理返回的方法签名
    -(void)forwardInvocation:(NSInvocation *)anInvocation{
        NSLog(@"4---%@",NSStringFromSelector(_cmd));
        NSLog(@"4-最后一步--%@",anInvocation);
        if ([NSStringFromSelector(anInvocation.selector) isEqualToString:@"gogogo"]) {
            [anInvocation invokeWithTarget:[UnknownModel2 new]];
        }else{
            [super forwardInvocation:anInvocation];
        }
    }
    //触发崩溃
    - (void)doesNotRecognizeSelector:(SEL)aSelector {
        
    }
    
    打印结果如下:
    2018-12-27 00:14:00.469445+0800 iOS_KnowledgeStructure[7940:110114] 1---gogogo
     2018-12-27 00:14:00.469613+0800 iOS_KnowledgeStructure[7940:110114] 1---resolveInstanceMethod:
     2018-12-27 00:14:00.469765+0800 iOS_KnowledgeStructure[7940:110114] 2---gogogo
     2018-12-27 00:14:00.469873+0800 iOS_KnowledgeStructure[7940:110114] 2---forwardingTargetForSelector:
     2018-12-27 00:14:00.469978+0800 iOS_KnowledgeStructure[7940:110114] 3---gogogo
     2018-12-27 00:14:00.470097+0800 iOS_KnowledgeStructure[7940:110114] 3---methodSignatureForSelector:
     2018-12-27 00:14:00.470247+0800 iOS_KnowledgeStructure[7940:110114] 1---_forwardStackInvocation:
     2018-12-27 00:14:00.470355+0800 iOS_KnowledgeStructure[7940:110114] 1---resolveInstanceMethod:
     2018-12-27 00:14:00.470765+0800 iOS_KnowledgeStructure[7940:110114] 4---forwardInvocation:
     2018-12-27 00:14:00.471367+0800 iOS_KnowledgeStructure[7940:110114] 4-最后一步--<NSInvocation: 0x600002442000>
     2018-12-27 00:14:00.471969+0800 iOS_KnowledgeStructure[7940:110114] lalalalala---gogogo
    

    相关文章

      网友评论

          本文标题:434,利用OC对象的消息重定向forwardingTarget

          本文链接:https://www.haomeiwen.com/subject/mdsizktx.html