首先,要说明一下Other Linker Flags
究竟是用来干吗的。说白了,就是ld
命令除了默认参数外的其余参数。ld
命令实现的是连接器的工做,详细说明能够在终端man ld
查看。php
若是有人不清楚连接器是什么东西的话,我能够做个简单的说明。app
一个程序从简单易读的代码到可执行文件每每要经历如下步骤:函数
源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 连接器 > 可执行文件this
源文件通过一系列处理之后,会生成对应的.obj
文件,而后一个项目必然会有许多.obj
文件,而且这些文件之间会有各类各样的联系,例如函数调用。连接器作的事就是把这些目标文件和所用的一些库连接在一块儿造成一个完整的可执行文件。spa
可能我描述的比较肤浅,由于我本身了解的也不是很深,建议你们读一下这篇文章,能够对连接器作的事情有个大概的了解:连接器作了什么.net
苹果官方Q&A上有这么一段话:翻译
The "selector not recognized" runtime exception occurs due to an issue between the implementation of standard UNIX static libraries, the linker and the dynamic nature of Objective-C. Objective-C does not define linker symbols for each function (or method, in Objective-C) - instead, linker symbols are only generated for each class. If you extend a pre-existing class with categories, the linker does not know to associate the object code of the core class implementation and the category implementation. This prevents objects created in the resulting application from responding to a selector that is defined in the category.code
翻译过来,大概意思就是Objective-C
的连接器并不会为每一个方法创建符号表,而是仅仅为类创建了符号表。这样的话,若是静态库中定义了已存在的一个类的分类,连接器就会觉得这个类已经存在,不会把分类和核心类的代码合起来。这样的话,在最后的可执行文件中,就会缺乏分类里的代码,这样函数调用就失败了。ci
解决方法在背景那块我就提到了,就是在Other Linker Flags
里加上所需的参数,用到的参数通常有如下3个:get
-ObjC
-all_load
-force_load
下面来讲说每一个参数存在的意义和具体作的事情。
首先是-ObjC
,通常这个参数足够解决前面提到的问题,苹果官方说明以下:
This flag causes the linker to load every object file in the library that defines an Objective-C class or category. While this option will typically result in a larger executable (due to additional object code loaded into the application), it will allow the successful creation of effective Objective-C static libraries that contain categories on existing classes.
简单说来,加了这个参数后,连接器就会把静态库中全部的Objective-C
类和分类都加载到最后的可执行文件中,虽然这样可能会由于加载了不少没必要要的文件而致使可执行文件变大,可是这个参数很好地解决了咱们所遇到的问题。可是事实真的是这样的吗?
若是-ObjC
参数真的这么有效,那么事情就会简单多了。
Important: For 64-bit and iPhone OS applications, there is a linker bug that prevents -ObjC from loading objects files from static libraries that contain only categories and no classes. The workaround is to use the -allload or -forceload flags.
当静态库中只有分类而没有类的时候,-ObjC
参数就会失效了。这时候,就须要使用-all_load
或者-force_load
了。
-all_load
会让连接器把全部找到的目标文件都加载到可执行文件中,可是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,而后又使用了这个参数,那么你颇有可能会遇到ld: duplicate symbol
错误,由于不一样的库文件里面可能会有相同的目标文件,因此建议在遇到-ObjC
失效的状况下使用-force_load
参数。
-force_load
所作的事情跟-all_load
实际上是同样的,可是-force_load
须要指定要进行所有加载的库文件的路径,这样的话,你就只是彻底加载了一个库文件,不影响其他库文件的按需加载。