对于load方法的理解

写在前面

关于load方法我相信大家应该有所了解。这篇文章主要目的是记录我在看 ObjC源码时对于load方法的一些新的认知,所以在这篇文章里面会粘贴部分关键的 ObjC源码。


+ load 是 Objective-C 中的一个方法,它是一个在整个文件被加载到运行时,在 main 函数调用之前被 ObjC 运行时调用的方法。


这篇文章会介绍+ load方法的三个问题:


+ load方法是如何被调用的。

+ load方法的调用顺序。

+ load方法的作用。

load方法是如何被调用的

我们可以很清楚的看到,在+load方法之前,被调用的方法有:

1call_class_loads()2call_load_methods3load_images4dyld::notifySingle(dyld_image_states, ImageLoader const*)11_dyld_start

(滑动显示更多)

dyld 是 the dynamic link editor 的缩写,它是苹果的动态链接器。

在我们启动App时,真正的加载过程是从exec()函数开始,系统会调用exec()函数创建进程,并且分配内存空间。然后会执行以下的操作


把App对应的可执行文件加载到内存。

把dyld加载到内存。dyld也是一个可执行的程序。

dyld进行动态链接。

dyld的具体工作内容:


dyld会找到可执行文件的依赖动态库。接着dyld会将所依赖的动态库加载到内存中。这是一个递归的过程,依赖的动态库可能还会依赖别的动态库,所以dyld会递归每个动态库,直至所有的依赖库都被加载完毕。

Rebase和Binding。

每当有新的镜像加载之后,都会执行 3 load_images 方法进行回调,这里的回调是在整个运行时初始化时 _objc_init 注册的。

关于镜像的概念:

Mach-O 是 iOS 系统不同运行时期可执行的文件的文件类型统称。

Mach-O 有三种文件类型: Executable、Dylib、Bundle。

Executable:app 的二进制主文件,同时也是 app extension 的二进制主文件。

Dylib:动态库。

Bundle:资源文件包。

镜像文件包含了上述的三种文件类型。


看到load_images方法

首先会调用 prepare_load_methods 对 load 方法的调用进行准备。

prepare_load_methods方法的作用:

递归地加载当前类和没有调用+ load 父类进入加载列表,在将当前类加入加载列表之前,会先把父类加入待加载的列表,保证父类在子类前调用 load 方法。


然后开始调用call_load_methods方法。

其中 call_class_loads 会从一个待加载的类列表 loadable_classes 中寻找对应的类,然后找到 @selector(load) 的实现并执行。

这个时候就执行了[XXX load]方法了。


load方法的调用顺序

当父类和子类都实现load函数时,父类的load方法执行顺序要优先于子类

当一个类未实现load方法时,不会调用父类load方法

类中的load方法执行顺序要优先于类别(Category)

当有多个类别(Category)都实现了load方法,这几个load方法都会执行,但执行顺序不确定(其执行顺序与类别在Compile Sources中出现的顺序一致)

有多个不同的类的时候,每个类load 执行顺序与其在Compile Sources出现的顺序一致

load方法的作用

在main运行之前,load 方法就会调用。


由于它的调用不是惰性的,且其只会在程序调用期间调用一次,最最重要的是,如果在类与分类中都实现了 load 方法,它们都会被调用,不像其它的在分类中实现的方法会被覆盖,这就使 load 方法成为了方法交换(Method Swizzling)的绝佳时机。


load方法注意:

load调用时机比较早,当load调用时,其他类可能还没加载完成,运行环境不安全,不过在这个时间点,所有的 framework 都已经加载到了运行时中,所以调用 framework 中的方法都是安全的。

load方法是线程安全的,它使用了锁,我们应该避免线程阻塞在load方法。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容