美文网首页
深入理解iOS消息转发机制

深入理解iOS消息转发机制

作者: 程序员不务正业 | 来源:发表于2018-05-17 10:57 被阅读7次

    消息转发流程图

    image

    向一个对象发送消息时,
    首先会在对象类的cache,method list以及父类对象的cache,method list依次查找SEL对应的IMP

    如果没有找到,并且实现了动态方法决议机制就会决议。如果没有实现动态决议机制或者决议失败且实现了消息转发机制。就会进入消息转发流程。否则程序Crash.

    进入消息转发 objc——msgSend(id, SEL,...)来实现消息转发

    动态方法决议

    字面上我的理解是:消息在发送过程中进行判断到底这消息该由谁接收

    一:询问是否有动态添加方法来进行处理

    Objective C 提供了一种名为动态方法决议的手段,使得我们可以在运行时动态地为一个 selector 提供实现。我们只要实现

    +resolveInstanceMethod: 
    +resolveClassMethod: 
    

    并在其中为指定的 selector 提供实现即可(通过调用运行时函数 class_addMethod 来添加)。这两个方法都是 NSObject 中的类方法
    实现

    //People.m
    void speak(id self, SEL _cmd){
        NSLog(@"Now I can speak.");
    }
    + (BOOL)resolveInstanceMethod:(SEL)sel {
        NSLog(@"resolveInstanceMethod:  %@", NSStringFromSelector(sel));
        if (sel == @selector(speak)) {
            class_addMethod([self class], sel, (IMP)speak, "V@:");
            return YES;
        }
        return [super resolveInstanceMethod:sel];
    }
    
    + (BOOL)resolveClassMethod:(SEL)name  
    {  
        NSLog(@" >> Class resolving %@", NSStringFromSelector(name));  
          
        return [super resolveClassMethod:name];  
    }
    
    

    二:询问有没有别人能够帮忙处理一下

     - (id)forwardingTargetForSelector:(SEL)aSelector
    

    使用如下

    - (id)forwardingTargetForSelector:(SEL)aSelector {
        NSLog(@"forwardingTargetForSelector:  %@", NSStringFromSelector(aSelector));
        Bird *bird = [[Bird alloc] init];
        if ([bird respondsToSelector:aSelector]) {
            return bird;
        }
        return [super forwardingTargetForSelector: aSelector];
    }
    // Bird.m
    - (void)fly {
        NSLog(@"I am a bird, I can fly.");
    }
    

    三:在一和二中都没能处理掉时会进入

    - (void)forwardInvocation:(NSInvocation *)anInvocation {
        NSLog(@"forwardInvocation: %@", NSStringFromSelector([anInvocation selector]));
        if ([anInvocation selector] == @selector(code)) {
            Monkey *monkey = [[Monkey alloc] init];
            [anInvocation invokeWithTarget:monkey];
        }   
    }
    
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
        NSLog(@"method signature for selector: %@", NSStringFromSelector(aSelector));
        if (aSelector == @selector(code)) {
            return [NSMethodSignature signatureWithObjCTypes:"V@:@"];
        }
        return [super methodSignatureForSelector:aSelector];
    }
    

    END

    最后消息未能处理的时候,还会调用到

    - (void)doesNotRecognizeSelector:(SEL)aSelector
    

    我们也可以在这个方法中做些文章,避免掉crash,但是只建议在线上环境的时候做处理,实际开发过程中还要把异常抛出来

    相关文章

      网友评论

          本文标题:深入理解iOS消息转发机制

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