让静态库中的 Category 可用
让静态库中的 Category 可用
前几天将常用的代码封装成静态库( .a )供给其他项目使用。在使用的过程中我们发现,编译到静态库中的 Category 都无法使用。使用的时候会导致崩溃并提示找不到该方法。
原因
这需要从编译链接这部分开始说起。对于编译型语言(如,c、c++)来讲,编译器会把源文件(.c,.cpp)转化为对象文件(.o)。对象文件中包含了符号、代码和数据,并且与源文件一一对应。当我们组建动态库(.dylib)或运行程序等的时候,这些文件会被链接器链接起来组成一个可被操作系统识别运行的文件。
但是对于 .a 来讲,它其实是对对象文件的一个归档。在使用的时候,编译器会根据归档里去检测哪些 .a 中有哪些符号被引用了。只有包含有引用的符号的对象文件才会被链接器真正的载入,并被链接进程处理。
与 C/C++ 这类语言不通,OC 语言非常依赖于 Runtime 特性。Category 是 Runtime 下特有的特性,不会像类、函数一样被符号化,也就是说,编译器不能检测到 Category 是否被使用了。这就出现一种情况,我们编写了该部分代码到.a 中,但是编译器没有检测到 Category 使用,所以没有载入运行期变得可用。
解决方法
-
Other Linker Flags 中添加 -all_load
加载全部的对象文件,不管是否应用到。但是可能会产生很大的二进制文件。不推荐
-
Other Linker Flags 中添加 -force_load 与指定路径。 不推荐
这种方法和-all_load很像,不同的是它只载入指定的归档
-
Other Linker Flags 中添加 -ObjC
使用这种方法不会载入任何没有OC代码的文件 推荐
-
启用 Xcode 中 build setting 中的 Perform Single-Object PreLink
所有的对象文件都会被合并成一个单文件(不是真正的链接,所以叫做预链接),现在如果主对象文件中的任何符号被认为是“在使用”,整个主对象文件都会被认为在使用,这样它里面的OC部分就会被载入了。不推荐
-
在 Category 中添加 Fake symbol,并保证在程序中引用。
不推荐