load
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.
直接通过函数地址调用,而不是objc_msgSend,所以分类和主类的load、子类和父类的load互不影响。
load_method_t load_method = (load_method_t)classes[i].method; (*load_method)(cls, @selector(load));
load_method_t load_method = (load_method_t)cats[i].method; cls = _category_getClass(cat); (*load_method)(cls, @selector(load));
先执行主类的load,再执行分类的load
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);
先执行父类的load,再执行子类的load
// Ensure superclass-first ordering schedule_class_load(cls->getSuperclass());
按照编译顺序,先编译先执行(父类的分类的加载与子类的分类的加载的先后也取决于编译顺序)
classref_t const *classlist = _getObjc2NonlazyClassList(mhdr, &count); category_t * const *categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
load的执行时机。动态库或可执行文件加载时执行。
/*********************************************************************** * load_images * Process +load in the given images which are being mapped in by dyld. **********************************************************************/ void load_images(const char *path __unused, const struct mach_header *mh)
通过类结构里的标志位,保证每个类的load只加入列表一次。如果没有这个标志位判断,那么沿着
superclass
调用时应该会导致重复加入列表。分类没有这个标志位,是因为分类不需要superclass-first
。// class +load has been called #define RW_LOADED (1<<23) static void schedule_class_load(Class cls) { if (!cls) return; ASSERT(cls->isRealized()); // _read_images should realize if (cls->data()->flags & RW_LOADED) return; // Ensure superclass-first ordering schedule_class_load(cls->getSuperclass()); add_class_to_loadable_list(cls); cls->setInfo(RW_LOADED); }
类和分类的load方法的从准备到执行,而且只执行一次,是通过动态数组来维护的。
// List of classes that need +load called (pending superclass +load) // This list always has superclasses first because of the way it is constructed static struct loadable_class *loadable_classes = nil; static int loadable_classes_used = 0; static int loadable_classes_allocated = 0; // List of categories that need +load called (pending parent class +load) static struct loadable_category *loadable_categories = nil; static int loadable_categories_used = 0; static int loadable_categories_allocated = 0;
Loading Comments...