- +initialize方法在類第一次接收到消息的時(shí)候被調(diào)用
-
調(diào)用順序
1.先調(diào)用父類的,再調(diào)用子類的
2.如果子類沒(méi)實(shí)現(xiàn)+initialize方法拂到,會(huì)調(diào)用父類的+initialize痪署。所以父類的+initialize可能被調(diào)用多次
3.如果分類實(shí)現(xiàn)了+initialize,會(huì)覆蓋類本身的+initialize
源碼分析
源碼版本objc4-781.tar.gz
首先查找函數(shù)調(diào)用順序兄旬,在類中重寫(xiě)+initialize狼犯,添加斷點(diǎn)。得到函數(shù)的調(diào)用棧领铐。
所以源碼解讀順序?yàn)?br>
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)
這里主要關(guān)注最后兩個(gè)方法
/***********************************************************************
* 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()) {
// 遞歸調(diào)用悯森,父類的initialize在子類之前調(diào)用
initializeNonMetaClass(supercls);
}
...省略部分代碼...
{
// 調(diào)用initialize方法
callInitialize(cls);
if (PrintInitializing) {
_objc_inform("INITIALIZE: thread %p: finished +[%s initialize]",
objc_thread_self(), cls->nameForLogging());
}
}
...省略部分代碼...
}
在void initializeNonMetaClass(Class cls)
中可以看到首先會(huì)去判斷父類是否初始化過(guò)了,如果沒(méi)有調(diào)用父類的+ initialize方法绪撵,保證父類的+ initialize在子類之前調(diào)用瓢姻。
接下來(lái)是callInitialize
方法
void callInitialize(Class cls)
{
((void(*)(Class, SEL))objc_msgSend)(cls, @selector(initialize));
asm("");
}
可以看到callInitialize
中直接通過(guò)objc_msgSend
方法調(diào)用+initialize方法。這也就解釋了為什么+initialize子類沒(méi)實(shí)現(xiàn)音诈,會(huì)去調(diào)用父類中的幻碱。category中的會(huì)覆蓋類本身的。