美文网首页
一个方法从开始调用,直到崩溃或者执行都会经历哪些步骤?

一个方法从开始调用,直到崩溃或者执行都会经历哪些步骤?

作者: 地上的 | 来源:发表于2018-05-21 22:35 被阅读0次

    (以最新runtime.h源码为例,objc4-723)
    当调用一个方法[ object sendMessage ]的时候,会发生如下情况:
    (1)首先会根据接收器对象的isa指针获取object的所属的类别Class,比如NSObject类。
    (2)优先从这个类中的cache里查找sendMessage方法,如果找不到,就会在methodList里面去找。
    (3)如果当前Class没找到,就会去super_class里面继续找。

    class.png

    一、找得到的情况

    (1)如果找到了method,就会执行他实现的IMP。 method.png

    二、找不到的情况

    开始方法解析和消息转发过程。
    (1)Method Resolution
    首先会调用+(BOOL)resolveInstanceMethod:(SEL)sel,你需要做对应的处理,并且返回YES。

    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
        if (sel == @selector(sendMessage)) {
            class_addMethod([self class], sel, imp_implementationWithBlock(^(id self) {
                NSLog(@"method resolution way : send message");
            }), "v@*");
        }
        return YES;
    }
    

    如果返回NO或者什么都不写直接返回YES,就会走(2)。
    (2)Fast Forwarding
    执行- (id)forwardingTargetForSelector:(SEL)aSelector,将你调用的不存在的方法重定向到一个其他声明了这个方法的类,只需要你返回一个有这个方法的target,消息转发机制执行前,Runtime 系统允许我们替换消息的接收者为其他对象AnotherClass

    - (id)forwardingTargetForSelector:(SEL)aSelector
    {
        if (aSelector == @selector(sendMessage)) {
            return [AnotherClass new];
        }
        return nil;
    }
    

    如果return的是nil或者self,那就走(3)
    (3)Normal Forwarding
    首先调用- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector来获取你需要调用的sendMessage的参数和返回值。
    如果返回nil,就直接crash,抛出异常unrecognized selector sent to instance

    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
    {
        NSMethodSignature *methodSignature = [super methodSignatureForSelector:aSelector];
        if (!methodSignature) {
            methodSignature = [NSMethodSignature signatureWithObjCTypes:"v@:*"];
        }
        return methodSignature;
    }
    

    如果返回一个NSMethodSignature,系统就会创建一个NSInvocation对象(这也就是为什么这里叫Normal,而前面叫Fast),开始调用- (void)forwardInvocation:(NSInvocation *)anInvocation

    - (void)forwardInvocation:(NSInvocation *)anInvocation
    {
        AnotherClass *anotherClass = [AnotherClass new];
        if ([anotherClass respondsToSelector:anInvocation.selector]) {
            [anInvocation invokeWithTarget:anotherClass];
        }
    }
    

    这3种解决找不到方法的路子,优势不一。
    Method Resolution:仅是解析处理,只适用于在原来的类Object中代替。
    Fast Forwarding:它可以将消息处理转发给其他对象AnotherClass
    Normal Forwarding:它跟Fast Forwarding一样可以消息转发,但它能通过NSInvocation对象获取更多消息发送的信息,例如:targetselectorarguments返回值等信息。
    demo地址

    相关文章

      网友评论

          本文标题:一个方法从开始调用,直到崩溃或者执行都会经历哪些步骤?

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