返回
OC底层探究之Method慢速查找流程详解
IOS
2023-09-11 03:32:10
前言
在 《OC底层探究之从cache到objc_msgSend》 文章中,我们对 OC 运行时中方法调用的汇编快速查找流程进行了分析。本文将深入探究在快速查找流程失败后的慢速查找流程,进一步揭开 OC 底层方法调用的奥秘。
汇编慢速查找流程
当汇编快速查找流程(cache查找)失败时,系统将进入慢速查找流程,该流程主要包括以下几个步骤:
- 消息发送者检查: 检查消息发送者的类是否实现了所调用的方法。
- 父类查找: 如果消息发送者的类没有实现该方法,则向上查找父类是否实现了该方法。
- 元类查找: 如果父类查找也失败,则检查消息发送者的元类是否实现了该方法。
- 协议查找: 如果元类查找也失败,则遍历消息发送者实现的所有协议,检查这些协议是否实现了该方法。
- 动态方法解析: 如果所有查找都失败,则调用动态方法解析(
resolveInstanceMethod:
或resolveClassMethod:
)方法,尝试动态生成该方法。
慢速查找流程的汇编实现
慢速查找流程的汇编实现位于 objc-runtime-new.h
头文件中,主要包括以下几个汇编函数:
objc_msgSend_uncached
:未缓存的消息发送函数,用于触发慢速查找流程。objc_msgSend_lookup
:查找方法的函数,负责执行慢速查找流程中的查找步骤。objc_msgSend_imp
:执行方法的函数,在慢速查找流程成功找到方法后调用。
慢速查找流程的 C 语言实现
为了方便理解,我们将慢速查找流程的汇编实现转换为 C 语言,如下所示:
IMP objc_msgSend_uncached(id self, SEL op, ...) {
va_list args;
va_start(args, op);
IMP imp = objc_msgSend_lookup(self, op);
if (imp == NULL) {
// 动态方法解析
// ...
}
return imp;
}
IMP objc_msgSend_lookup(id self, SEL op) {
Class cls = object_getClass(self);
IMP imp = method_lookup(cls, op);
if (imp == NULL) {
// 父类查找
// ...
// 元类查找
// ...
// 协议查找
// ...
}
return imp;
}
慢速查找流程示例
下面是一个慢速查找流程的示例:
@interface MyClass : NSObject
@end
@implementation MyClass
- (void)myMethod {
NSLog(@"myMethod called");
}
@end
int main() {
MyClass *myObject = [[MyClass alloc] init];
[myObject performSelector:@selector(myMethod)]; // 调用 myMethod 方法
return 0;
}
在该示例中,当调用 [myObject performSelector:@selector(myMethod)]
时,系统会执行以下步骤:
- 快速查找流程失败,触发慢速查找流程。
- 慢速查找流程检查
MyClass
类是否实现了myMethod
方法,发现已实现。 - 查找成功,调用
myMethod
方法,输出"myMethod called"
。
结语
本文详细分析了 OC 底层方法调用的慢速查找流程,从汇编和 C 语言两个层面进行了阐述。通过理解慢速查找流程,我们可以更深入地掌握 OC 运行时的工作原理。