最近看了一篇iOS摸鱼周报里面关于一篇静态库和动态库的文章,发现和我之前理解的又不太一样了,学无止境呀!
静态库(Static Library)
- 静态库默认仅将有用到的类文件link 到 Mach-O 中 (以类文件为最小链接单位)。静态库中某个目标文件的代码没有被任何地方引用,则这个目标文件不会被链接到可执行文件中去,所以ipa包会小些。(为了 App 瘦身,尽量将代码放静态库中)
- App 冷启动速度快,前提是不使用动态库拆分搭配动态库懒加载方案
- 存在符号冲突可能
- 共享 TEXT 段
- 不需要额外签名验证
- 文件格式多为 fat 格式的静态库文件,形式多为 .a 与 .framework
动态库(Dynamic Library)
首先,对于动态库而言其实分动态链接库和动态加载库两种的,这两个最本质的区别还是加载时间。
动态链接库:在没有被加载到内存的前提下,当可执行文件被加载,动态库也随着被加载到内存中。这种和静态库一样程序启动被加载的。
动态加载库:当需要的时候再使用 dlopen 等通过代码或者命令的方式来加载,可在程序启动之后。
但是不论是哪种动态库,相比较与静态库,动态库处理起来要棘手的多。由于动态库是动态的,所以你事先不知道某个函数的具体地址。因此动态链接器在链接函数的时候需要做大量的工作。
苹果在iOS8后虽然开放了动态库的制作方式,但是embedded framework这种是阉割版的,和苹果自己的UIKit的动态库不一样的。苹果的动态库是多个app共享使用的。而我们自己封装的framework其实是被放到各自的app的bundle里面的,不同app同一个embedded framework也是需要各自加载的。
app1 和 app2 都有一个相同的 动态framework 以 Embedded 方式放入到各自的 app 中,当app1和app2先后被打开了,问这个 动态framework 会加载几次?
当然,不是一次,是两次。所以最妥当的应该这么说:对于相同路径的动态库,系统只会加载一次。(这里的动态库路径显然不一致,在各自的app中,而苹果自身的那些动态库,是放在同一个地方的。)
- ipa 包大(前提是不考虑懒加载的情况)动态库会把整个 lib 复制进 ipa 中。
- App 冷启动速度慢 (前提是用动态链接库)App 启动流程中有 rebase 和 bind,多个动态库只需要多次 rebase 和 bind。当然如果采用懒加载动态库的形式(动态加载库),能够加快 App 的启动速度,可以使用 dlopen 和 bundle 懒加载优化。
- 需要签名且需要验证签名。苹果会检查 framework 的签名,签名中必须包含 TeamIdentifier,并且 framework 和 host App 的 TeamIdentifier 必须一致,Xcode 重签名,保证动态库签名一致性
- App与动态库中重复代码可以共存,不会发生符号冲突