有load方法。
load方法在runtime加载类、分类的时候调用,调用方式是直接调用方法,而不是通过消息机制触发调用。
load
方法可以继承,但是一般情况下不会主动去调用load方法,都是让系统自动调用。
先调用类的load
方法。
按照编译先后顺序调用,先编译的先调用。
调用子类的load
方法之前会先调用父类的load
方法。
再调用分类的load
方法。
按照编译先后顺序调用,先编译的先调用。
// objc-os.mm/_objc_init(void) void _objc_init(void) { _dyld_objc_notify_register(&map_images, load_images, unmap_image); } // objc-runtime-new.mm/load_images void load_images(const char *path __unused, const struct mach_header *mh) { prepare_load_methods((const headerType *)mh); call_load_methods(); } // objc-runtime-new.mm / prepare_load_methods void prepare_load_methods(const headerType *mhdr) { size_t count, i; runtimeLock.assertWriting(); //获取所有的类 classref_t *classlist = _getObjc2NonlazyClassList(mhdr, &count); for (i = 0; i < count; i++) { // 整理要调用load方法的类 schedule_class_load(remapClass(classlist[i])); } //获取所有的分类 category_t **categorylist = _getObjc2NonlazyCategoryList(mhdr, &count); for (i = 0; i < count; i++) { category_t *cat = categorylist[i]; Class cls = remapClass(cat->cls); if (!cls) continue; // category for ignored weak-linked class realizeClass(cls); assert(cls->ISA()->isRealized()); add_category_to_loadable_list(cat); } } // objc-runtime-new.mm / schedule_class_load static void schedule_class_load(Class cls) { if (!cls) return; assert(cls->isRealized()); // _read_images should realize //类是否已经被加载到loadable_classes if (cls->data()->flags & RW_LOADED) return; // 确保父类排在前面 schedule_class_load(cls->superclass); add_class_to_loadable_list(cls); // 标志该类已经添加到了loadable_classes cls->setInfo(RW_LOADED); } // objc-loadmethod.mm / add_class_to_loadable_list void add_class_to_loadable_list(Class cls) { IMP method; loadMethodLock.assertLocked(); method = cls->getLoadMethod(); if (!method) return; // Don't bother if cls has no +load method if (PrintLoading) { _objc_inform("LOAD: class '%s' scheduled for +load", cls->nameForLogging()); } if (loadable_classes_used == loadable_classes_allocated) { loadable_classes_allocated = loadable_classes_allocated*2 + 16; loadable_classes = (struct loadable_class *) realloc(loadable_classes, loadable_classes_allocated * sizeof(struct loadable_class)); } loadable_classes[loadable_classes_used].cls = cls; loadable_classes[loadable_classes_used].method = method; loadable_classes_used++; } //objc-loadmethod.mm / call_load_methods void call_load_methods(void) { static bool 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) { //调用类的load方法 call_class_loads(); } // 2. Call category +loads ONCE // 调用Category的load方法 more_categories = call_category_loads(); // 3. Run more +loads if there are classes OR more untried categories } while (loadable_classes_used > 0 || more_categories); objc_autoreleasePoolPop(pool); loading = NO; } //objc-loadmethod.mm / call_class_loads static void call_class_loads(void) { int i; // Detach current loadable list. struct loadable_class *classes = loadable_classes; int used = loadable_classes_used; loadable_classes = nil; loadable_classes_allocated = 0; loadable_classes_used = 0; // Call all +loads for the detached list. for (i = 0; i < used; i++) { Class cls = classes[i].cls; // 取出load方法 load_method_t load_method = (load_method_t)classes[i].method; if (!cls) continue; if (PrintLoading) { _objc_inform("LOAD: +[%s load]\n", cls->nameForLogging()); } //调用load方法。 (*load_method)(cls, SEL_load); } // Destroy the detached list. if (classes) free(classes); } 复制代码
initialize
会在类第一次接受到消息的时候调用。与load
方法不同的是initialize
是通过消息机制调用的即通过objc_msgsend()
调用。
根据调用顺序触发。
调用子类的initialize
会先触发父类的initialize
。
// objc-runtime-new.mm / class_getInstanceMethod Method class_getInstanceMethod(Class cls, SEL sel) { if (!cls || !sel) return nil; lookUpImpOrNil(cls, sel, nil, NO/*initialize*/, NO/*cache*/, YES/*resolver*/); return _class_getMethod(cls, sel); } // objc-runtime-new.mm / lookUpImpOrNil IMP lookUpImpOrNil(Class cls, SEL sel, id inst, bool initialize, bool cache, bool resolver) { IMP imp = lookUpImpOrForward(cls, sel, inst, initialize, cache, resolver); if (imp == _objc_msgForward_impcache) return nil; else return imp; } // objc-runtime-new.mm / lookUpImpOrForward IMP lookUpImpOrForward(Class cls, SEL sel, id inst, bool initialize, bool cache, bool resolver) { IMP imp = nil; runtimeLock.read(); if (initialize && !cls->isInitialized()) { runtimeLock.unlockRead(); _class_initialize (_class_getNonMetaClass(cls, inst)); runtimeLock.read(); } return imp; } // objc-initialize.mm / _class_initialize void _class_initialize(Class cls) { assert(!cls->isMetaClass()); supercls = cls->superclass; // 递归调用,先调用父类的 initialize if (supercls && !supercls->isInitialized()) { _class_initialize(supercls); } callInitialize(cls); } // objc-initialize.mm / callInitialize void callInitialize(Class cls) { // 通过 objc_msgSend 进行调用 ((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize); asm(""); } 复制代码
调用方式
调用时刻
load、initialize的调用顺序?
load
再调用分类的load
initialize