iOS initialize

initialize 方法會在類第一次接收到消息時調(diào)用比如
[NSobject alloc]
調(diào)用順序
先調(diào)用父類的initialize在調(diào)用子類的initialize
(先初始化父類,在初始化子類,每個類都只會初始化一次)

initialize和load區(qū)別的是initialize是通過objc——msgsend調(diào)用的所以有以下特點
1、如果子類沒有實現(xiàn)initialize會調(diào)用父類的initialize(所以父類的initialize可能會被調(diào)用多次)
2、如果分類實現(xiàn)了initialize.就覆蓋類本身的initialize調(diào)用

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->getSuperclass();
//如果有父類并且父類沒有實例化先初始化父類
if (supercls  &&  !supercls->isInitialized()) {
    //通過遞歸方式傳入父類
    initializeNonMetaClass(supercls);
}

// Try to atomically set CLS_INITIALIZING.
SmallVector<_objc_willInitializeClassCallback, 1> localWillInitializeFuncs;
{
    monitor_locker_t lock(classInitLock);
    if (!cls->isInitialized() && !cls->isInitializing()) {
        cls->setInitializing();
        reallyInitialize = YES;

        // Grab a copy of the will-initialize funcs with the lock held.
        localWillInitializeFuncs.initFrom(willInitializeFuncs);
    }
}

if (reallyInitialize) {
    // We successfully set the CLS_INITIALIZING bit. Initialize the class.
    
    // Record that we're initializing this class so we can message it.
    _setThisThreadIsInitializingClass(cls);

    if (MultithreadedForkChild) {
        // LOL JK we don't really call +initialize methods after fork().
        performForkChildInitialize(cls, supercls);
        return;
    }
    
    for (auto callback : localWillInitializeFuncs)
        callback.f(callback.context, cls);

    // Send the +initialize message.
    // Note that +initialize is sent to the superclass (again) if 
    // this class doesn't implement +initialize. 2157218
    if (PrintInitializing) {
        _objc_inform("INITIALIZE: thread %p: calling +[%s initialize]",
                     objc_thread_self(), cls->nameForLogging());
    }

    // Exceptions: A +initialize call that throws an exception 
    // is deemed to be a complete and successful +initialize.
    //
    // Only __OBJC2__ adds these handlers. !__OBJC2__ has a
    // bootstrapping problem of this versus CF's call to
    // objc_exception_set_functions().
#if __OBJC2__
    @try
#endif
    {
       //第一次是傳入父類
       //第二次是傳入當前的類
        callInitialize(cls);

        if (PrintInitializing) {
            _objc_inform("INITIALIZE: thread %p: finished +[%s initialize]",
                         objc_thread_self(), cls->nameForLogging());
        }
    }
#if __OBJC2__
    @catch (...) {
        if (PrintInitializing) {
            _objc_inform("INITIALIZE: thread %p: +[%s initialize] "
                         "threw an exception",
                         objc_thread_self(), cls->nameForLogging());
        }
        @throw;
    }
    @finally
#endif
    {
        // Done initializing.
        lockAndFinishInitializing(cls, supercls);
    }
    return;
}

else if (cls->isInitializing()) {
    // We couldn't set INITIALIZING because INITIALIZING was already set.
    // If this thread set it earlier, continue normally.
    // If some other thread set it, block until initialize is done.
    // It's ok if INITIALIZING changes to INITIALIZED while we're here, 
    //   because we safely check for INITIALIZED inside the lock 
    //   before blocking.
    if (_thisThreadIsInitializingClass(cls)) {
        return;
    } else if (!MultithreadedForkChild) {
        waitForInitializeToComplete(cls);
        return;
    } else {
        // We're on the child side of fork(), facing a class that
        // was initializing by some other thread when fork() was called.
        _setThisThreadIsInitializingClass(cls);
        performForkChildInitialize(cls, supercls);
    }
}

else if (cls->isInitialized()) {
    // Set CLS_INITIALIZING failed because someone else already 
    //   initialized the class. Continue normally.
    // NOTE this check must come AFTER the ISINITIALIZING case.
    // Otherwise: Another thread is initializing this class. ISINITIALIZED 
    //   is false. Skip this clause. Then the other thread finishes 
    //   initialization and sets INITIALIZING=no and INITIALIZED=yes. 
    //   Skip the ISINITIALIZING clause. Die horribly.
    return;
}

else {
    // We shouldn't be here. 
    _objc_fatal("thread-safe class init in objc runtime is buggy!");
}
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • [toc] 參考 initialize load code objc4源碼解析 思路 既然 +initialize...
    felix6閱讀 749評論 0 2
  • +initialize方法 +initialize方法會在類第一次接收到objc_msgSend消息時調(diào)用 通過遞...
    dbmxl閱讀 927評論 0 0
  • ??我們都知道initialize方法只有當類或子類第一次收到消息時才會調(diào)用。我們在這個方法里打上斷點來看看,比如...
    水煮杰尼龜閱讀 1,424評論 0 5
  • 記錄一下initialize和load方法的調(diào)用時機 問題一 load和initialize哪個更早執(zhí)行? 1....
    霸_霸霸閱讀 388評論 0 1
  • 表情是什么,我認為表情就是表現(xiàn)出來的情緒。表情可以傳達很多信息。高興了當然就笑了,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 129,536評論 2 7

友情鏈接更多精彩內(nèi)容