+initialize方法

  • +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方法)