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

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

一个方法从开始调用,直到崩溃或者执行都会经历哪些步骤?_第1张图片
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地址

你可能感兴趣的:(一个方法从开始调用,直到崩溃或者执行都会经历哪些步骤?)