0%

iOS中关于Other Linker Flags

iOS中关于Other Linker Flags

iOS开发中,经常会用到一些第三方的静态库。导入编译的时候可能会遇到duplicate symbol错误。有的时候编译不报错运行的时候会报selector not recognized的错误。这时候我们需要在build setting中设置other linker flags加入参数-ObjC或者-all_load,就可以解决。那么,关于出现这些错误的原因?与other linker flags到底发挥的什么作用?

错误分析

duplicate symbol错误

原因:

  • 误将.m文件引入为头文件
  • 同一个工程中含有同名的文件。(同样的类名)
  • 引入的第三方框架包涵了与本地同名的文件
  • 第三方框架中包含相同的文件

解决:

首先排除第一种原因。然后可以根据错误的提示信息查看是哪个文件重复。

如图在错误提示中很清楚的知道是工程中的AudioPlayer文件与AmaiMedia.o中的冲突。这是根据你的项目中的情况进行修改。是修改静态库中的方便还是修改项目中的方便。一般情况是修改项目中的文件。(造成这种问题的原因是没有遵循苹果命名规范,没有加前缀。导致AudioPlayer这个类名冲突。以后命名的是要加上前缀后面跟上类名例如:ZCWAudioPlayer)

selector not recognized错误

原因:

  • 方法不存在
  • 内存管理不当
  • 静态库使用问题

解决:

第一种问题:检查拼写错误,检查该方法在当前的iOS版本是否可用

第二种问题:你的App试图引用一个已经被释放的对象.可以使用Zombies检查下问题原因。检查是否有内存越界的问题,可以开启内存防护,日志等选项,再添加异常断点。
第三种问题:静态库分类方法加载不当。在Other Linker Flags中设置-ObjC,-all_load,-force_load

连接器

一个程序从简单易读的代码到可执行文件往往要经历以下步骤:

源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件

源文件经过一系列处理以后,会生成对应的.obj文件,然后一个项目必然会有许多.obj文件,并且这些文件之间会有各种各样的联系,例如函数调用。链接器做的事就是把这些目标文件和所用的一些库链接在一起形成一个完整的可执行文件。

闪退原因

Objective-C的链接器并不会为每个方法建立符号表,而是仅仅为类建立了符号表。这样的话,如果静态库中定义了已存在的一个类的分类,链接器就会以为这个类已经存在,不会把分类和核心类的代码合起来。这样的话,在最后的可执行文件中,就会缺少分类里的代码,这样函数调用就失败了。

解决办法

在Other Linker Flags里面加上所需的参数。所需要的参数包括-ObjC、-all_load、-force_load

-ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中,虽然这样可能会因为加载了很多不必要的文件而导致可执行文件变大,但是这个参数很好地解决了我们所遇到的问题。但是并不是所有问题都能解决,当静态库中只有分类而没有类的时候,-ObjC参数就会失效了。这时候,就需要使用-all_load或者-force_load了。

-all_load:会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force_load参数

-force_load:所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载