记录于此!
1.代码层面验证
2.阅读源码
一、代码
推导:
1.只导入头文件,不会调用+initialize
2.第一次发消息时候调用+initialize,不发消息不会调用
二、源码
1.objc-initialize.mm文件
2.callInitialize方法
3.callInitialize方法
向上找到 _class_initialize方法
4.全局搜索_class_initialize方法
,在objc-runtime-new.mm文件
,发现lookUpImpOrForward方法
5.lookUpImpOrForward 方法
向上找到 _class_lookupMethodAndLoadCache3方法
6.全局搜索_class_lookupMethodAndLoadCache3方法
,然后在objc-msg-arm64.s
汇编文件中发现了bl __class_lookupMethodAndLoadCache3 汇编语句
7.发现bl __class_lookupMethodAndLoadCache3 汇编语句
在objc_msgSend
(objc_msgSend 是用汇编来实现的,为了效率)
以上是查找源码的顺序,其实不难发现:
· initialize是通过objc_msgSend调用
** 区分+load 方法,+load 是直接调用函数,而+initialize是消息发送机制
删减部分源码查看:
IMP lookUpImpOrForward(Class cls, SEL sel, id inst,
bool initialize, bool cache, bool resolver)
{
if (initialize && !cls->isInitialized()) {
runtimeLock.unlockRead();
_class_initialize (_class_getNonMetaClass(cls, inst));
runtimeLock.read();
// If sel == initialize, _class_initialize will send +initialize and
// then the messenger will send +initialize again after this
// procedure finishes. Of course, if this is not being called
// from the messenger then it won't happen. 2778172
}
}
判断是否需要初始化initialize 且 该类没有被初始化过,然后进入_class_initialize
方法,同样只保留精华代码。
void _class_initialize(Class cls)
{
supercls = cls->superclass;
if (supercls && !supercls->isInitialized()) {
_class_initialize(supercls);
}
callInitialize(cls);
}
递归调用,先调用父类,然后调用子类
总结:
1.第一次发消息时候调用+initialize,不发消息不会调用
2.+initialize 会先调用父类,然后调用子类的
3.每一个类只会initialize一次(父类的initialize方法可能会被调用多次,因为是消息发送机制,因为如果子类没有实现+initialize,会调用父类的+initialize)
4.类别中的+initialize会覆盖类中的+initialize(消息机制,多个类别实现执行最后一个)