返回
imp 慢速查找_ObjC 底层原理(08)
IOS
2024-01-26 11:35:33
在上一篇文章 底层原理(07) 中,分析了方法的快速查找流程即缓存查找,如果缓存中没有找到就会。。。下面就会进入方法慢速查找流程。。。
一. __objc_msgSend_uncached
在当前类中,
- (void)sayHi;
生成一个 _objc_msgSend_uncached 消息。进入 __objc_msgSend_uncached 的流程:
// 如果缓存查找结果是 null,就会进入这个流程,开始慢速查找。
objc_method_t objc_msgSend_uncached(id self, SEL op, ...) {
// setup a call frame to try finding the message
struct objc_super super;
// 因为类的元类是类,对象也存在自己的元类,所以需要一个结构体来存储父类和对象类对应的类。
super.receiver = (id)self;
super.class = object_getClass((id)self);
// sender 指向方法调用者,就是当前的对象。
void *sender = &super;
// 找到这个类的方法,如果方法不存在,返回 null,我们再从超类开始找。
objc_method_t result = _objc_msg_lookup_method((id)self, op, sender);
// 既然进入了慢速查找,那么肯定找不到对应的缓存,首先从当前类开始查找方法。
// 调用 _objc_msg_lookup_method() 函数,返回方法结构体。
// 因为这个方法没有缓存,所以我们必须调用查找方法的方法来得到它的方法结构体。
if (result) {
// 若当前类有这个方法,那么就是调用了 - (void)sayHi 这个方法,根据前面章节的知识,调用
// _objc_msgSend_cached 就实现了消息的发送。
// 查找到了方法,那么缓存起来。
_cache_method(self, op, result, sender);
} else {
// 如果在当前类没有找到,则继续向上递归寻找。
result = _objc_msg_lookup_super(super.receiver, op, &super.class);
// 这里继续向父类查找方法,如果父类中存在这个方法,那么就返回对应的方法结构体。
// 如果父类不存在这个方法,返回 null,继续在父类的父类中查找。
if (result) {
// 如果有父类调用父类中的方法,这种方法就是 override,然后缓存起来。
_cache_method(self, op, result, sender);
}
}
return result;
}
二. 查找步骤
如果缓存查找失败,那么就需要使用慢速查找的方法 __objc_msgSend_uncached 来查找方法。
这个函数会尝试从当前类及其超类中查找指定的方法。如果找到,则会将其缓存起来,以加快下次查找的速度。
- 调用 __objc_msg_lookup_method 函数在当前类中查找方法。
- 如果在当前类中没有找到,则继续向上递归寻找。
- 如果在任何超类中都找不到,则返回 null。
三. 使用 __objc_msgSend_uncached 方法
- (void)sayHi;
生成一个 _objc_msgSend_uncached 消息。进入 __objc_msgSend_uncached 的流程,查找方法并缓存起来,然后调用 _objc_msgSend_cached 函数发送消息。
- (void)sayHi;
{
id self, _cmd;
// 发送消息
__objc_msgSend_uncached(self, _cmd);
}