在写 《iOS:load方法能不能被hook?》 和 《iOS启动优化:App启动耗时在线监控与AppDelegate管控》 两篇文章时都提到了动态库的加载,由于主题的原因,没有详细介绍,有同学对这个比较感兴趣,今天我们就来研究下在iOS中动态库的加载顺序是什么样子的。
1.实验篇
我们先通过demo看下几种Case:
没有依赖关系:
我们制作dylibA
、dylibB
、dylibB
这三个动态库(不了解动态库的制作的请问度娘...),且它们没有依赖关系,同时我们在每个库中添加一个Class,暂且以Class的load方法的调用顺序当做是动态库的加载顺序(先挖一个坑),比如dylibA
:@implementation ClassA
+ (void)load {
NSLog(@"dylibA loaded");
}
@end将这三个库加到demo工程中,并且保证
Build Phases
-Link Binary With Libraries
中的顺序:dylibA
>dylibB
>dylibC
,运行结果:Demo[53199:17384949] dylibA loaded
Demo[53199:17384949] dylibB loaded
Demo[53199:17384949] dylibC loaded我们调整下
Link Binary With Libraries
中的顺序:dylibC
>dylibB
>dylibA
,运行结果:Demo[53265:17397552] dylibC loaded
Demo[53265:17397552] dylibB loaded
Demo[53265:17397552] dylibA loaded通过实验我们知道:在没有依赖关系的情况下,动态库的加载顺序由
Link Binary With Libraries
中的顺序决定,当然我们可以通过Link Binary With Libraries
来控制动态库的加载顺序。单一依赖关系
dylibA
依赖dylibB
,dylibB
依赖dylibC
,我们简单改造下这三个库,如在dylibB
中import下dylibC
的头文件,dylibA
中同理:#import "ClassB.h"
#import >dylibC/dylibC.h<
@implementation ClassB
+ (void)load {
NSLog(@"dylibB loaded");
}
@endLink Binary With Libraries
中的顺序:dylibA
>dylibB
>dylibC
,运行结果:Demo[53570:17450857] dylibC loaded
Demo[53570:17450857] dylibB loaded
Demo[53570:17450857] dylibA loaded这次我们发现三个库的加载顺序是反的,我们修改下顺序:
dylibC
>dylibA
>dylibB
,运行结果不变。由实验结果可知:动态库的加载顺序还受依赖关系影响,被依赖的子节点优先加载。
组合依赖关系
其中,
dylibA
、dylibB
、dylibB
没有依赖关系,dylibA
依赖了dylibD
、dylibE
、dylibF
。Demo[97898:19286936] dylibD loaded
Demo[97898:19286936] dylibF loaded
Demo[97898:19286936] dylibE loaded
Demo[97898:19286936] dylibA loaded
Demo[97898:19286936] dylibB loaded
Demo[97898:19286936] dylibC loaded通过修改
dylibA
-Link Binary With Libraries
中dylibD
、dylibE
的顺序调整为:Demo[97982:19305235] dylibF loaded
Demo[97982:19305235] dylibE loaded
Demo[97982:19305235] dylibD loaded
Demo[97982:19305235] dylibA loaded
Demo[97982:19305235] dylibB loaded
Demo[97982:19305235]