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

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

作者: 地上的 | 来源:发表于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地址

相关文章

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

    (以最新runtime.h源码为例,objc4-723)当调用一个方法[ object sendMessage ]...

  • 浏览器输入url以后都发生了什么

    从输入一个网址开始,都调用了哪些服务,经历了哪些步骤,深度解析。以输入www.google.com为例。 1. C...

  • Java——Join()

    调用某个线程的Join方法时,这个方法会挂起调用线程,直到被调用线程结束执行,调用线程才会继续执行。 public...

  • 有点难度的10道java面试题

    1.jvm对频繁调用的方法做了哪些优化?java虚拟机最开始是通过解释器进行解释执行的,当虚拟机发现某个方法或者代...

  • 主线程和子线程结束的关系

    线程是一个动态执行的过程,它也有一个从产生到死亡的过程。 主线程从main()方法开始执行,直到main()方法结...

  • js概念一:调用堆栈

    步骤:当脚本调用函数时,解释器将其添加到调用堆栈,然后开始执行该函数。 当函数调用的任何函数都会进一步添加到调用堆...

  • Thread类常用方法

    常用方法 join 当某个程序执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加...

  • vue-resource中的Promise对象

    vue-resource基本HTTP调用和RESTful调用action方法执行后都会返回一个Promise对象,...

  • 理解“对象等同性”概念

    调用“isEqualToString”比调用“isEqual”方法快,后者还要执行额外步骤,因为它不知道受测对象的...

  • 多线程-join

    join:加入线程,顺序执行。 官方解释:当我们调用某个线程的这个方法时,这个方法会挂起调用线程,直到被调用线程结...

网友评论

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

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