OC中的方法调用,其实都是转换为objc_msgSend函数的调用
objc_msgSend的执行流程可以分为3大阶段
-
消息发送
-
动态方法解析
-
消息转发
1.消息发送
- 在发送消息前,首先要检查receiver是否为nil,如果是nil则直接退出。所以给nil发送任何消息都不会报错。
- 如果不是nil,则从reveiverClass的cache中查找方法。如果没有查找到则进入步骤3。
- 从reveiverClass的class_rw_t中查找方法,如果找到,调用方法,结束查找 并将方法缓存到reveiverClass的cache中。如果没有找到进入步骤4。
- 从superClass的cache中查找方法,如果找到,调用方法,结束查找 并将方法缓存到reveiverClass的cache中。如果没有找到进入步骤5。
- 从superClass的class_rw_t中查找方法,如果找到,调用方法,结束查找 并将方法缓存到reveiverClass的cache中。如果没有找到则继续查找父类,在步骤4-5之间循环,直至没有父类,则进入步骤6。
- 进入动态方法解析阶段。
tip:不管是在哪一级找到的方法,最后都会被缓存在reveiverClass的cache中。
2.动态方法解析
-
首先根据 triedResolver 判断是否有解析过,如果没有解析,进入步骤2,如果已经解析过,进入步骤3。
-
根据不同的receiver调用不同的方法,并将 triedResolver 状态设为 Yes。并重新进入 消息发送 阶段 第2步。
如果是类对象: +resolveInstanceMethod:
如果是元类对象: +resolveClassMethod:
-
进入 消息转发 阶段
3.消息转发
- 调用 + 或- forwardingTargetForSelector: 方法,如果返回值不为nil,则 objc_msgSend(返回值, SEL) ,如果nil进入步骤2。
- 调用 + 或- methodSignatureForSelector: 方法,如果返回值不为nil,调用 forwardInvocation: 方法,如果nil则调用我们熟悉的 调用doesNotRecognizeSelector:方法。