pre-main
静态库
汇编生成的目标与引用的库一起打包到可执行文件生成最终的mach-o二进制可执行文件
动态库
程序编译的时候不会链接到动态库,程序运行才会链接, 动态库包括uikit, foundation,corefoundation, libdispatch,dyld等
dyld会首先读取mach-o的header和loadcommonds,获取路径,加载相关依赖库,例如加载动态库A到内存,然后检查A所依赖的动态库
(通常一个APP要加载的动态库100-400个),
load_images方法主要做两件事, prepare_load_methods call_load_methods, 在call_load_methods里先调用 class_loads,再调用 category_loads
即先去除类,父类和分类的load方法, 第二步加载这些load方法, load方法在这里进行初始化
+load方法应用场景 (hook方法 / 组件化开发, 不同组件之间的通信,在load方法中注册协议)
1. +load是在类和分类在加载时调用的, 2. 只调用一次
顺序是
1. 类优先与分类调用
2. 子类调用+load时,先调用父类的+load, ( 父类优先于子类, 与继承不同)
3. 不同类按照编译顺序调用+load方法(先编译先调用)
4, 分类也是按照编译顺序调用+load方法(先编译先调用)
其中:
schedule_class_load(cls->superclass); //在调度类的load方法前,要先跳用父类的load方法(递归),决定了父类优先于子类调用
add_class_to_loadable_list(cls); //添加到能够加载的类的列表中
当prepare_load_methods函数执行完之后,所有满足+load方法调用条件的类和分类就被分别保持在全局变量中; 等待执行
当prepare_load_methods执行完,准备好类和分类后,就该调用他们的+load方法啦,在call_load_methods中进行调用;注意图中红色圈内部分,两个关键函数:call_class_loads(),call_category_loads() ;看到这两个函数想到了什么呢?
对,就是这两个函数决定了类优先与分类调用+load方法;
说明:+load方法是系统根据方法地址直接调用,并不是objc_msgSend函数调用(isa,superClass);这就决定了如果子类没有实现+load方法,那么当它被加载时runtime是不会调用父类的+load方法的,除非父类也实现了+load方法;