initialize方法與load方法比較

jialebaba發表於2019-02-26

load方法和initialize方法類似點

    1. 都只會呼叫一次
    2. 父類在子類之前載入
複製程式碼

不同點在於:

    1. 載入時間不同,load方法在main()函式前進行呼叫,initialize在第一次呼叫類的所屬方法時在呼叫<可能永遠不呼叫>。
    2. load方法不會被Category覆蓋。
複製程式碼

initialize原始碼

//向物件傳送訊息時,lookUpImpOrForward函式判斷物件是否初始化,沒有初始化則先初始化在呼叫類的方法
IMP lookUpImpOrForward(Class cls, SEL sel, id inst, bool initialize, bool cache, bo ol resolver);
//第一次呼叫類
if (initialize && !cls->isInitialized()) {
      _class_initialize (_class_getNonMetaClass(cls, inst));
  }
  
// 第一次呼叫類的方法,初始化物件
void _class_initialize(Class cls) {
    Class supercls;
    bool reallyInitialize = NO;
    // 遞迴初始化父類
    supercls = cls->superclass;
    if (supercls && !supercls->isInitialized()) {
          _class_initialize(supercls);
    }
    {
        monitor_locker_t lock(classInitLock);
        if (!cls->isInitialized() && !cls->isInitializing()) {
              cls->setInitializing();
              reallyInitialize = YES;
        }
    }
    if (reallyInitialize) { 
        _setThisThreadIsInitializingClass(cls);
        if (MultithreadedForkChild) { performForkChildInitialize(cls, supercls);
            return;
    }
        @try {
            // 通過objc_msgSend函式呼叫initialize方法
                callInitialize(cls);
          }
        @catch (...) { 
            @throw;
        }
        @finally {
            // 執行initialize方法後,進行系統的initialize過程
            lockAndFinishInitializing(cls, supercls);
        }
        return;
    }
    else if (cls->isInitializing()) {
        if (_thisThreadIsInitializingClass(cls)) {
            return;
        } else if (!MultithreadedForkChild) {
            waitForInitializeToComplete(cls);
            return; 
        } else {
        _setThisThreadIsInitializingClass(cls);
        performForkChildInitialize(cls, supercls);
        }
    }
}
複製程式碼

相關文章