最近深究了下依赖静态库分类,链接参数需要-ObjC的问题。
静态库
首先需要介绍一下我对静态库的理解。
分类
静态库本质上就是目标文件,是还没有链接的文件。静态库分两种:
-
目标文件
.o
; -
目标文件archive,通常是
.a
形式;
.a
就是若干目标文件的集合压缩,可以通过ar来创建、查看和解压。
//创建
ar -r XX.a -A.o -B.o
//查看
ar -t XX.a
//解压
ar -x XX.a
.a文件结构
可以参考.a结构
合并.o
.a
只是.o
文件的简单压缩,每一个.o
文件都保留了完整的MachO文件结构,这会造成浪费。所以可以通过合并.o
文件来减小大小。
//这样合并会让所有符号都隐藏,可以加上-keep_private_externs
ld -r -o DD.o D1.o D2.o D3.o
我测试后,一个76MB大小的.a
文件,可以缩小成7.5MB大小的.a
文件。
合并.o的缺点
但是Xcode默认创建的静态库工程,生成的产物格式都是.a,
很明显合并.o这个方法是有缺点的。
缺点就是,当你直接链接.o
时,无论是否用到其中的符号,都会将.o
里所有的符号都链接。
而使用.a
时,只会链接用到的符号所在的.o
的所有符号。
静态库OC分类方法
当我们链接静态库时,当静态库含有OC的分类,需要在链接参数加上-ObjC
,否则会出现unrecognized selector
报错。那么,为什么会出现这种报错呢?
OC方法调用
上面链接.a
说了,引用到对应.o
里的符号,才会链接所有符号,而OC方法是动态调用的。
大部分OC方法都是通过objc_msgSend
调用的,你调用的方法,只是作为selector(也就是个字符串)传给了objc_msgSend
,其实根本没引用到任何符号。
那对于OC对象,什么时候才引用到了符号呢?调用类的时候。比如[XXClass alloc]
,这时候引用到了符号XXClass。XXClass所在的.o
文件就会被链接进来。
OC静态库结构
可以看到分类和主类不是一个.o
,当你调用分类方法时,分类.o
里的符号你是一个也没引用到,分类.o
完全没有被链接。所以才会导致报错。
如果你尝试在主类的.h
和.m
里声明分类,你就会发现一切都正常了。这是因为分类符号和主类符号都在一个.o
里,虽然只用到了主类的符号,但是分类也一起被链接进来了。
或者尝试在分类头文件声明一个C的函数或变量,主程序引用,你会发现也不会报错了。
总结
-
链接
.a
时,用到里面哪个.o
的符号,对应.o
里的所有符号就都会链接进来,没有的.o
就不会被链接进来。 -
合并
.o
可以缩小体积,但是会导致所有符号都链接。文章来源:https://www.toymoban.com/news/detail-407625.html -
静态库有分类要加
-ObjC
的原因是,分类和主类在两个.o
里,分类的符号没有被引用到,所以分类.o
没有被链接。文章来源地址https://www.toymoban.com/news/detail-407625.html
到了这里,关于iOS——从静态库到分类加载-ObjC的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!