void load_images(const char *path __unused, const struct mach_header *mh) { // Return without taking locks if there are no +load methods here. if (!hasLoadMethods((const headerType *)mh)) return;
// Re-entrant calls do nothing; the outermost call will finish the job. if (loading) return; loading = YES; // 创建了自动释放池 void *pool = objc_autoreleasePoolPush();
do { // 循环调用 class +load 方法,直到 loadable_classes 空 while (loadable_classes_used > 0) { call_class_loads(); }
在 Xcode 中点击 Edit Scheme,添加两个环境变量并将 Value 置为 YES:(可以在执行load方法以及加载category的时候打印log信息):
OBJC_PRINT_LOAD_METHODS:YES
OBJC_PRINT_REPLACED_METHODS:YES
打印信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
objc[31269]: LOAD: class 'Person' scheduled for +load objc[31269]: LOAD: class 'Teacher' scheduled for +load objc[31269]: LOAD: class 'Animal' scheduled for +load
objc[31269]: LOAD: category 'Teacher(CategoryForTeacher)' scheduled for +load objc[31269]: LOAD: category 'Person(Category_One)' scheduled for +load objc[31269]: LOAD: category 'Person(Category_Two)' scheduled for +load
objc[31286]: LOAD: class 'Animal' scheduled for +load objc[31286]: LOAD: class 'Person' scheduled for +load objc[31286]: LOAD: class 'Teacher' scheduled for +load
objc[31286]: LOAD: category 'Person(Category_One)' scheduled for +load objc[31286]: LOAD: category 'Teacher(CategoryForTeacher)' scheduled for +load objc[31286]: LOAD: category 'Person(Category_Two)' scheduled for +load
当我们给某个类发送消息的时候,runtime会调用这个函数在类中查找相应方法的实现或转发。 IMP lookUpImpOrForward(Class cls, SEL sel, id inst, bool initialize, bool cache, bool resolver) { // 如果类没有初始化,runtime 会调用 void _class_initialize(Class cls) 函数对该类进行初始化 if (initialize && !cls->isInitialized()) { runtimeLock.unlock(); _class_initialize (_class_getNonMetaClass(cls, inst)); runtimeLock.lock(); // 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 } }
// 通过递归调用保证父类先于子类调用 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 状态为 Initializing cls->setInitializing(); // 设置 flag 值,保证下面进入初始化处理逻辑 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. // 将 initialize 的方法调用放在安全县城内执行 _setThisThreadIsInitializingClass(cls);
if (MultithreadedForkChild) { // 不会在被 fork() 之后调用 +initialize 方法 performForkChildInitialize(cls, supercls); return; } // 这里省略了一些 tay-catch 及打印逻辑 // 真正调用 cls 的 +initialize 方法,点击进去查看其实就是 // ((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize); callInitialize(cls); // 结束 initialize lockAndFinishInitializing(cls, supercls); return; } // 如果当前 cls 正在 initialize 中 else if (cls->isInitializing()) { // 初始化已设置好,无需做任何操作 // 如果这个线程在前面设置了它,则继续正常运行 if (_thisThreadIsInitializingClass(cls)) { return; } // 如果其它线程设置,则阻塞,直至初始化完成 else if (!MultithreadedForkChild) { waitForInitializeToComplete(cls); return; } else { // 我们位于fork()的子线程,面对的是一个在调用fork()时由其他线程初始化的类。 _setThisThreadIsInitializingClass(cls); performForkChildInitialize(cls, supercls); } } // 如果当前 cls initialize 结束 else if (cls->isInitialized()) { return; } else { // We shouldn't be here. _objc_fatal("thread-safe class init in objc runtime is buggy!"); } }