当我们在接入一个新的SDK时,有时会遇到这么个问题:当前项目中存在与新接入的SDK相同的依赖文件,导致接入后报符号冲突错误。如下所示
ld: 2 duplicate symbols for architecture arm64
利用动态库解决第三方静态库与项目符号冲突问题,下面简单模拟下这个场景。
1、新建一个demo工程和一个静态库A,两个工程中都新建一个person类。注:新建的framework默认是动态库,需前往Build Settings中,将Mach-o Type设置成Static Library.
2、假设A库是我们准备引入的新的库,它里边包含了与demo工程相同的类Person。当我们引入A库后会出现如下错误:
3、下面我们来解决这个问题,在两个项目Person中添加run方法如下图
4、新建一个动态库B,并将静态库A拖入动态库B中,并将静态库A的头文件复制一份放入库B中,添加UseP类添加use方法,暴露对应的头文件给外部调用,如图所示;
5、编译生成动态库,拖进demo工程中,并按图配置
6、在viewController里添加测试代码运行
成功运行,下面分析测试log,通过不断调整,结果发现,在主工程中引入头文件后,直接通过Person类创建对象调用run方法实际上得到的是demo工程的Persion,而在动态库B中创建并使用的Person是静态库A中的。那么静态库A中使用的是否是自身的Person呢?我们继续验证
7、在静态库A中添加TestPerson类,并添加代码如下,配置头文件,重新编辑framework添加动态库B中。
8、修改动态库B中UseP类的use 方法如下图,编译后重新放入demo工程
9、运行demo工程,输出如下
得出的结果正是我们想要的,demo工程中使用的是自身的person,而静态库A中自身使用的则是自身的person。虽然通过runtime实际上生成的也是静态库A中的person,实际上在开发中我们也很少使用runtime方式创建使用对象,所以这个也没什么影响。
10、那么如果符号冲突的是两个静态库的情况呢?下面继续探究,创建静态库C,并添加person对象以及实现
11、编译后添加进demo工程,并删除demo工程的Person,运行demo工程输出如下:
无论怎么调整库B与C的顺序,结果都是一样,外部调用的仍是原本的Person(静态库或demo工程里的),而动态库B里的库A使用的还是自身的Person。
结论
利用动态库解决第三方静态库与项目符号冲突问题时,demo工程中使用的是自身(或其他静态库)中的person,而静态库A在经过一层动态库封装后自身使用的还是自身的person。虽然通过runtime实际上生成的也是静态库A中的person,但在开发中我们也很少使用runtime方式创建使用对象,所以这个也是可以避免的。