iOS——从静态库到分类加载-ObjC

最近深究了下依赖静态库分类,链接参数需要-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可以缩小体积,但是会导致所有符号都链接。

  • 静态库有分类要加-ObjC的原因是,分类和主类在两个.o里,分类的符号没有被引用到,所以分类.o没有被链接。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值