真的了解 + load 方法么?
+load 作为 Objective-C 中的一个方法,与其它方法有很大的不同。它只是一个在整个文件被加载到运行时,在 main 函数调用之前被 ObjC 运行时调用的钩子方法。其中关键字有这么几个:
- 文件刚加载
- main函数之前
- 钩子方法
准备 + load 方法
在load_images 方法,如果在扫描镜像的过程中发现了 + load 符号
就会进入 load_images_nolock 来查找 load 方法
调用 prepare_load_methods 对 load 方法的调用进行准备(将需要调用 load 方法的类添加到一个列表中,后面的小节中会介绍)
通过 _getObjc2NonlazyClassList 获取所有的类的列表之后,会通过 remapClass 获取类对应的指针,然后调用 schedule_class_load 递归地安排当前类和没有调用 + load 父类进入列表。
在执行 add_class_to_loadable_list(cls) 将当前类加入加载列表之前,会先把父类加入待加载的列表,保证父类在子类前调用 load 方法。
调用 + load 方法
在将镜像加载到运行时、对 load 方法的准备就绪之后,执行 call_load_methods,开始调用 load 方法
其中 call_class_loads 会从一个待加载的类列表 loadable_classes 中寻找对应的类,然后找到 @selector(load) 的实现并执行。
调用顺序如下:
1.不停调用类的 + load 方法,直到 loadable_classes 为空
2.调用一次 call_category_loads 加载分类
3.如果有 loadable_classes 或者更多的分类,继续调用 load 方法
相比于类 load 方法的调用,分类中 load 方法的调用就有些复杂了:
1.获取当前可以加载的分类列表
2.如果当前类是可加载的 cls && cls->isLoadable() 就会调用分类的 load 方法
3.将所有加载过的分类移除 loadable_categories 列表
4.为 loadable_categories 重新分配内存,并重新设置它的值
调用的顺序
对于 load 方法的调用顺序有两条规则:
父类先于子类调用
类先于分类调用
load 的应用
load 可以说我们在日常开发中可以接触到的调用时间最靠前的方法,在主函数运行之前,load 方法就会调用。
由于它的调用不是惰性的,且其只会在程序调用期间调用一次,最最重要的是,如果在类与分类中都实现了 load 方法,它们都会被调用,不像其它的在分类中实现的方法会被覆盖,这就使 load 方法成为了方法调剂的绝佳时机。
但是由于 load 方法的运行时间过早,所以这里可能不是一个理想的环境,因为某些类可能需要在在其它类之前加载,但是这是我们无法保证的。不过在这个时间点,所有的 framework 都已经加载到了运行时中,所以调用 framework 中的方法都是安全的。