Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.
Declaration
+ (void)load; Discussion
The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond. The order of initialization is as follows: All initializers in any framework you link to. All +load methods in your image. All C++ static initializers and C/C++ __attribute__(constructor) functions in your image. All initializers in frameworks that link to you.
In addition: A class’s +load method is called after all of its superclasses’ +load methods. A category +load method is called after the class’s own +load method. In a custom implementation of load you can therefore safely message other unrelated classes from the same image, but any load methods implemented by those classes may not have run yet.
Important Custom implementations of the load method for Swift classes bridged to Objective-C are not called automatically.
/*********************************************************************** * load_images * Process +load in the given images which are being mapped in by dyld. * * Locking: write-locks runtimeLock and loadMethodLock **********************************************************************/ void load_images(constchar *path __unused, conststruct mach_header *mh) { // Return without taking locks if there are no +load methods here. if (!hasLoadMethods((const headerType *)mh)) return;
/*********************************************************************** * prepare_load_methods * Schedule +load for classes in this image, any un-+load-ed * superclasses in other images, and any categories in this image. **********************************************************************/ // Recursively schedule +load for cls and any un-+load-ed superclasses. // cls must already be connected. staticvoid schedule_class_load(Class cls) { if (!cls) return; assert(cls->isRealized()); // _read_images should realize // 判断class结构体信息中是否加载的标记 if (cls->data()->flags & RW_LOADED) return;
/*********************************************************************** * call_load_methods * Call all pending class and category +load methods. * Class +load methods are called superclass-first. * Category +load methods are not called until after the parent class's +load. **********************************************************************/ void call_load_methods(void) { staticbool loading = NO; bool more_categories;
loadMethodLock.assertLocked();
// Re-entrant calls do nothing; the outermost call will finish the job. if (loading) return; loading = YES;
void *pool = objc_autoreleasePoolPush();
do { // 1. Repeatedly call class +loads until there aren't any more while (loadable_classes_used > 0) { call_class_loads(); }
// 2. Call category +loads ONCE more_categories = call_category_loads();
// 3. Run more +loads if there are classes OR more untried categories } while (loadable_classes_used > 0 || more_categories);
Initializes the class before it receives its first message.
Declaration
+ (void)initialize;
Discussion
The runtime sends initialize to each classin a program just before the class, or any class that inherits from it, is sent its first message from within the program. Superclasses receive this message before their subclasses. The runtime sends the initialize message to classes in a thread-safe manner. That is, initialize is run by the first thread to send a message to a class, and any other thread that tries to send a message to that class will block until initialize completes. The superclass implementation may be called multiple times if subclasses do not implement initialize—the runtime will call the inherited implementation—or if subclasses explicitly call [super initialize]. If you want to protect yourself from being run multiple times, you can structure your implementation along these lines: + (void)initialize { if (self == [ClassName self]) { // ... do the initialization ... } } Because initialize is called in a blocking manner, it’s important to limit method implementations to the minimum amount of work necessary possible. Specifically, any code that takes locks that might be required by other classes in their initialize methods is liable to lead to deadlocks. Therefore, you should not rely on initialize for complex initialization, and should instead limit it to straightforward, class local initialization.
/*********************************************************************** * lookUpImpOrForward. * The standard IMP lookup. * initialize==NO tries to avoid +initialize (but sometimes fails) **********************************************************************/ IMP lookUpImpOrForward(Class cls, SEL sel, id inst, bool initialize, bool cache, bool resolver) { if (initialize && !cls->isInitialized()) { runtimeLock.unlockRead(); _class_initialize (_class_getNonMetaClass(cls, inst)); runtimeLock.read(); // If sel == initialize, _class_initialize will send +initialize and // then the messenger will send +initialize again after this // procedure finishes. Of course, if this is not being called // from the messenger then it won't happen. 2778172 } }
/*********************************************************************** * class_initialize. Send the '+initialize' message on demand to any * uninitialized class. Force initialization of superclasses first. **********************************************************************/ void _class_initialize(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是否初始化,没有的话通过递归先初始化supercls supercls = cls->superclass; if (supercls && !supercls->isInitialized()) { _class_initialize(supercls); } // Try to atomically set CLS_INITIALIZING. { monitor_locker_t lock(classInitLock); if (!cls->isInitialized() && !cls->isInitializing()) { cls->setInitializing(); reallyInitialize = YES; } } 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; } // Send the +initialize message. // Note that +initialize is sent to the superclass (again) if // this class doesn't implement +initialize. 2157218 // 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);