前言
在上一篇文章中(手把手带你探索load底层原理)探索了load的调用机制,本文是探索一下initialize的调用机制,并比较一下异同点。
+initialize其实在平时开发中用的较少,一般用来初始化常量,不过面试中常会问到它与+load的区别。
initialize调用规则
+initialize方法是在类或它的子类收到第一条消息之前被调用的,这里所指的消息包括实例方法和类方法的调用。也就是说+initialize方法是以懒加载的方式被调用的,如果程序一直没有给某个类或它的子类发送消息,那么这个类的+initialize方法是永远不会被调用的。- 当子类没有实现
+initialize或者子类在+initialize中显式的调用了[super initialize],那么父类的+initialize方法会被调用多次。 - 在分类实现
+initialize,会只执行分类的+initialize - 类的
+initialize方法在所有父类的+initialize方法调用之后调用
验证调用规则
这次是在objc源码中直接调试代码,在我提供的源码里新建一个target, 如下图

接下来创建Person类,实现load和initialize方法,编译运行我们刚才创建的target

运行结果只执行了load方法,并没有执行initialize方法,所以能够得到结论:load在文件被加载时就执行了,initialize不主动调用
对于本文开头的几个结论,可以在这里都简单用代码验证一遍,我这里就不再去一一验证了,直接开始探索源码。
探索
我在load里打印了一下self,发现initialize被调用了,那么看看断点处的initialize

发现这里其实就进入到了runtime的消息查找流程,这里直接来到第三步,这里判断是否类已经初始化,没有初始化就做初始化操作。所以在这里可以验证开头的结论一,它是收到类的第一条消息后才调用的。

看看_class_initialize函数
void _class_initialize(Class cls)
{
assert(!cls->isMetaClass());
Class supercls;
bool reallyInitialize = NO;
// Make sure super is done initializing BEFORE beginning to initialize cls.
// See note about deadlock above.
supercls = cls->superclass;
if (supercls && !supercls->isInitialized()) {
_class_initialize(supercls);
}
// Try to atomically set CLS_INITIALIZING.
{
monitor_locker_t lock(classInitLock);
if (!cls->isInitialized() && !cls->isInitializing()) {
cls->setInitializing();
reallyInitialize = YES;
}
}
//其余代码省略
callInitialize(cls);
-
这里有一个标识符
reallyInitialize,在cls->setInitializing()(给类的isa设置RW_INITIALIZING标识),设置完后改为true -
这里有拿到
supercls,然后判断是否存在和是否初始化完成,未初始化则调用自己本身这个函数_class_initialize,其实就是一个递归,用来确保所有父类的initialize已经执行完,再执行当前类,这里和之前探索load的时候的递归调用父类load的方法原理相同。所以在这里可以验证开头的结论四:类的+initialize方法在所有父类的+initialize方法调用之后调用。
void callInitialize(Class cls)
{
((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize);
asm("");
}
- 最后会调用
callInitialize, 使用了发送消息objc_msgSend的方式对+initialize方法进行调用。也就是说+initialize方法的调用与普通方法的调用是一样的,走的都是发送消息的流程。换言之,如果子类没有实现+initialize方法,那么继承自父类的实现会被调用;所以有了结论三:如果一个类的分类实现了+initialize方法,那么就会对这个类中的实现造成覆盖。 - 因此,这里验证了开头的结论二:如果一个子类没有实现 +initialize 方法,那么父类的实现是会被执行多次的。
总结
