OC中的initialize方法调用的源码
我在最新版的objc中找到initializeNonMetaClass,源码如下:
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()) { 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!"); } }
上面一大坨代码,我个人认为真正有用的就是两端代码:
// Make sure super is done initializing BEFORE beginning to initialize cls. // See note about deadlock above. supercls = cls->superclass; if (supercls && !supercls->isInitialized()) { // 在这里递归调用了initializeNonMetaClass initializeNonMetaClass(supercls); }
{ callInitialize(cls); if (PrintInitializing) { _objc_inform("INITIALIZE: thread %p: finished +[%s initialize]", objc_thread_self(), cls->nameForLogging()); } }
上面两段代码意思,调用本类的Initialize方法之前,通过递归调用父类的Initialize,然后在调用本类的
callInitialize源码如下:
void callInitialize(Class cls) { ((void(*)(Class, SEL))objc_msgSend)(cls, @selector(initialize)); asm(""); }