美文网首页
+initialize方法

+initialize方法

作者: Nomo_C | 来源:发表于2020-05-20 22:32 被阅读0次
    • +initialize方法在类第一次接收到消息的时候被调用
    • 调用顺序
      1.先调用父类的,再调用子类的
      2.如果子类没实现+initialize方法,会调用父类的+initialize。所以父类的+initialize可能被调用多次
      3.如果分类实现了+initialize,会覆盖类本身的+initialize

    源码分析

    源码版本objc4-781.tar.gz
    首先查找函数调用顺序,在类中重写+initialize,添加断点。得到函数的调用栈。

    image.png

    所以源码解读顺序为
    objc-runtime-new.mm
    IMP lookUpImpOrForward(id inst, SEL sel, Class cls, int behavior)
    static Class initializeAndLeaveLocked(Class cls, id obj, mutex_t& lock)
    static Class initializeAndMaybeRelock(Class cls, id inst,
    void initializeNonMetaClass(Class cls)
    void callInitialize(Class cls)
    这里主要关注最后两个方法

    
    /***********************************************************************
    * class_initialize.  Send the '+initialize' message on demand to any
    * uninitialized class. Force initialization of superclasses first.
    **********************************************************************/
    void initializeNonMetaClass(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()) {
            // 递归调用,父类的initialize在子类之前调用
            initializeNonMetaClass(supercls);
        }
        
        ...省略部分代码...
            {
                //  调用initialize方法
                callInitialize(cls);
    
                if (PrintInitializing) {
                    _objc_inform("INITIALIZE: thread %p: finished +[%s initialize]",
                                 objc_thread_self(), cls->nameForLogging());
                }
            }
        ...省略部分代码...
    }
    
    

    void initializeNonMetaClass(Class cls)中可以看到首先会去判断父类是否初始化过了,如果没有调用父类的+ initialize方法,保证父类的+ initialize在子类之前调用。
    接下来是callInitialize方法

    void callInitialize(Class cls)
    {
        ((void(*)(Class, SEL))objc_msgSend)(cls, @selector(initialize));
        asm("");
    }
    

    可以看到callInitialize中直接通过objc_msgSend方法调用+initialize方法。这也就解释了为什么+initialize子类没实现,会去调用父类中的。category中的会覆盖类本身的。

    相关文章

      网友评论

          本文标题:+initialize方法

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