Runtime - 消息发送机制

926 阅读2分钟

OC中的方法调用,其实都是转换为objc_msgSend函数的调用

objc_msgSend的执行流程可以分为3大阶段

  • 消息发送

  • 动态方法解析

  • 消息转发

1.消息发送

  1. 在发送消息前,首先要检查receiver是否为nil,如果是nil则直接退出。所以给nil发送任何消息都不会报错。
  2. 如果不是nil,则从reveiverClass的cache中查找方法。如果没有查找到则进入步骤3。
  3. 从reveiverClass的class_rw_t中查找方法,如果找到,调用方法,结束查找 并将方法缓存到reveiverClass的cache中。如果没有找到进入步骤4。
  4. 从superClass的cache中查找方法,如果找到,调用方法,结束查找 并将方法缓存到reveiverClass的cache中。如果没有找到进入步骤5。
  5. 从superClass的class_rw_t中查找方法,如果找到,调用方法,结束查找 并将方法缓存到reveiverClass的cache中。如果没有找到则继续查找父类,在步骤4-5之间循环,直至没有父类,则进入步骤6。
  6. 进入动态方法解析阶段。

tip:不管是在哪一级找到的方法,最后都会被缓存在reveiverClass的cache中。

2.动态方法解析

  1. 首先根据 triedResolver 判断是否有解析过,如果没有解析,进入步骤2,如果已经解析过,进入步骤3。

  2. 根据不同的receiver调用不同的方法,并将 triedResolver 状态设为 Yes。并重新进入 消息发送 阶段 第2步。

    如果是类对象: +resolveInstanceMethod:

    如果是元类对象: +resolveClassMethod:

  3. 进入 消息转发 阶段

3.消息转发

  1. 调用 + 或- forwardingTargetForSelector: 方法,如果返回值不为nil,则 objc_msgSend(返回值, SEL) ,如果nil进入步骤2。
  2. 调用 + 或- methodSignatureForSelector: 方法,如果返回值不为nil,调用 forwardInvocation: 方法,如果nil则调用我们熟悉的 调用doesNotRecognizeSelector:方法。

暂时先这样 回头补上源代码配合解释更酸爽