探究+initialize本质

作者: 我是C | 来源:发表于2018-08-20 20:26 被阅读113次

记录于此!

1.代码层面验证
2.阅读源码

一、代码


image.png

推导:
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(消息机制,多个类别实现执行最后一个)

相关文章

网友评论

    本文标题:探究+initialize本质

    本文链接:https://www.haomeiwen.com/subject/itlliftx.html