1、类和分类的+load方法调用顺序
分析源码:
_objc_init(运行时初始化方法)
↓
load_images(加载模块方法)
↓
call_load_methods(调用load方法)
↓
call_class_loads(调用类的load方法)
↓
call_category_loads(调用分类的load方法)
static void call_class_loads(void)
{
// 读取所有类
struct loadable_class *classes = loadable_classes;
......
// 遍历所有类
for (i = 0; i < used; i++) {
// 找到class对象中的+load方法指针
load_method_t load_method = (load_method_t)classes[i].method;
// 调用+load方法
(*load_method)(cls, @selector(load));
}
......
}
static bool call_category_loads(void)
{
// 读取所有分类
struct loadable_category *cats = loadable_categories;
......
// 遍历所有分类
for (i = 0; i < used; i++) {
// 找到分类里+load方法指针
load_method_t load_method = (load_method_t)cats[i].method;
// 调用+load方法
(*load_method)(cls, @selector(load));
}
......
}
由源码可知,先调用了call_class_loads方法再调用了call_category_loads方法,所以类和分类调用顺序是:
先调用所有类中的+load方法,再调用所有分类的+load方法。
2、不同类间的+load方法调用顺序
分析运行时源码:
prepare_load_methods(预加载+load方法)
↓
schedule_class_load(定制类的load方法)
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);
}
通过分析源码可知:schedule_class_load方法内部有一个递归调用,每次传入参数是cls的superclass,将cls添加到loadable_classes数组中,所以最终结果导致在loadable_classes数组中父类class会排在子类class前面,再结合call_class_loads方法得出:
1、先调用父类中的+load方法,再调用子类中的+load方法。
2、没有继承关系的类,按照编译顺序调用+load方法。
3、不同分类间的+load方法调用顺序
分析源码:
void add_category_to_loadable_list(Category cat)
{
......
loadable_categories[loadable_categories_used].cat = cat;
......
}
结合call_category_loads方法得出:
分类是按照编译顺序调用+load方法
4、总结
4.1、+load方法特点
+load方法会在runtime加载类、分类时调用
每个类、分类的+load,在程序运行过程中只调用一次
+load是通过方法指针调用,所以分类+load方法不会覆盖类的+load方法
4.2、调用顺序
先调用类的+load
按照编译先后顺序调用(先编译,先调用)
调用子类的+load之前会先调用父类的+load
再调用分类的+load
按照编译先后顺序调用(先编译,先调用)