load方法
在objc源码的objc-os.mm
类里面void _objc_init(void)
这个方法,是运行时启动的方法,在这个方法里会加载所有load方法,这个方法里会调用runtime
的void load_images(const char *path __unused, const struct mach_header *mh)
方法,然后在里面调用void prepare_load_methods(const headerType *mhdr)
方法会将所有类里面的load方法和分类里面的load方法存储起来。
- 类的load方法是通过
void add_class_to_loadable_list(Class cls)
里面存储 - 分类的load方法是通过
void add_category_to_loadable_list(Category cat)
里面存储
存储完以后回到load_images
里调用void call_load_methods(void)
,这个就是调用所有的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方法的调用。
继承时的情况
如果存在继承的情况下,是先调用父类在调用子类的。
通过源码void prepare_load_methods(const headerType *mhdr)
里的static void schedule_class_load(Class cls)
可以看出。
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->superclass);
add_class_to_loadable_list(cls);
cls->setInfo(RW_LOADED);
}
可以看出schedule_class_load
这个方法的参数是一个Class
,这个方法里面就是调用add_class_to_loadable_list
,然后将Class
的load方法存储起来。但是在调用add_class_to_loadable_list
之前是先递归调用自己的,将自己的superclass
当做参数传入,于是父类就会先于自己被存储起来。
所以父类的load
方法会被先调用。
总结
- load方法是在程序启动的时候去调用(runtime加载类和分类的时候)
- load方法只会调用一次(由函数地址调用,主动调用,并非有消息机制调用。)
- 会先调用所有类的load方法,再去调用各个分类的load方法
-
load
方法的调用顺序是先调用父类,再调用子类。当所有参与编译的非分类的load
全部执行调完以后,才会去按照编译顺序去逐个调用各个分类的load
。
-
- 分类里的load方法不会影响到原始类里的load方法
- 分类的load方法调用顺序是看编译先后,先被编译的会被先调用