iOS OC 方法查找流程
前言
上一篇关于方法的本质
的探索中,我们知道了方法
的底层是调用objc_msgSend
发送消息,并对objc_msgSend
的底层汇编进行了分析。当用汇编
快速查找,未查找到方法缓存
时,会调用 MethodTableLookup
,然后调用_class_lookupMethodAndLoadCache3
,从汇编
转到C
,开启一系列的慢速查找,接下来我们对_class_lookupMethodAndLoadCache3
的方法查找流程进行分析。
1. _class_lookupMethodAndLoadCache3
方法查找流程
假如当调用LGStudent
调用对象方法sayHello
时,底层通过objc_msgSend
发送消息,通过汇编在LGStudent
的 cache中快速查找sayHello
的缓存,未找到时,会来的_class_lookupMethodAndLoadCache3
,方法如下:
IMP _class_lookupMethodAndLoadCache3(id obj, SEL sel, Class cls)
{
return lookUpImpOrForward(cls, sel, obj,
YES/*initialize*/, NO/*cache*/, YES/*resolver*/);
// NO/*cache*/ 没有方法缓存
}
在IMP lookUpImpOrForward()
方法中
- 先根据传入的参数
cache
,为ture
时,再次通过cache_getImp(cls, sel)
方法,用汇编去查找imp
,查找到直接返回imp
;为false
时,直接跳过。 - 判断
!cls->isRealized()
,调用realizeClass(cls)
,做准备工作(根据class
中rw data()->flags & RW_REALIZED
),比如父类 元类 rw ro
等。
if (!cls->isRealized()) {
realizeClass(cls);
}
- 准备工作完成后,再次尝试
cache_getImp(cls, sel)
,查找到imp
,直接返回imp
.
imp = cache_getImp(cls, sel);
if (imp) goto done;
-
试图在
class's method lists
中查找方法
,通过getMethodNoSuper_nolock
获取meth
4.1.getMethodNoSuper_nolock
中:循环取出
mlists
后,调用method_t *m = search_method_list(*mlists, sel)
,通过sel
去匹配,匹配到直接返回。