如果你经常困惑 iOS 开发中的静态库和动态库的作用与区别, 那么这篇文章可以为你解惑

静态库简单的理解是多个目标文件 (, 以 为后缀) 的打包集合. 静态库的存在形式:
-
Mac/iOS: 或封装成
讯享网 -
讯享网
Linux: -
Windows:
查看 object file 格式:
-
讯享网
提供的是目标文件, 所以不需要重新编译, 只需要链接即可 -
加载 App 速度更快, 因为在编译时已经进行了链接, 因此启动时不需要进行二次查找启动
动态库 (, 也称作 , , ), 跟静态库一样是多个 封装起来的, 但是动态库并不会在编译时直接置入 app, 而是将动态库的信息置入 app, 然后 app 在被运行的时候去动态查找动态库并进行链接, 这一步也叫做 .
根据动态库的载入时间 () 我们将动态库分为以下两种:
- : 在启动 app 时立刻将动态库进行加载 (随程序启动而启动)
- : 当需要的时候再使用
讯享网
等通过代码或者命令的方式来加载 (在程序启动之后)
以上行为是由动态链接器 (, macOS 称 ) 来完成
动态库的存在形式分为以下几种:
-
MacOS/iOS: , 或封装成 -
讯享网
Linux: -
Windows:
macOS 大规模地使用 , 可以前往路径 文件夹查看系统的动态库.

然而在运行时进行才做链接其实是一个笨重的负担, 应合理安排哪些库需要 以及时机.
因为动态库不需要在编译时置入 app 中, 因此理论上体积会更小, 而且可以做到动态库内容改变所有结果文件不需要重新编译即可获得最新功能
以上只是对于标准的系统动态库来说的, 对于 iOS 开发来说, 因为我们只能使用 来使用动态库, 这样的动态库并不是真正的动态库, 其会在编译时全部置入 app, 然后在 app 启动时全部加载, 这样的话会导致体积大, 加载速度慢.
标准的动态库与静态库定义如上, 但是在 iOS 系统中, Apple 为我们提出了另一种可以包含依赖库的模式 –
一个 其实就是一个有着特定结构的文件夹装着各种共享的资源. 这些资源通常是 图片, Xibs, 动态库, 静态库, 文档 等, 毫不掩饰的表明它纯粹就是一个文件夹.


- : 包含了 对外公开的 , Swift 并不会用到这些 , 如果你的 是用 写的, Xcode 会自动帮你创建这个文件夹以提供互用性.
- : 包含了 LLVM, Swift 的 Module 信息. .modulemap 档案是给 Clang 使用的.
文件夹下的档案类似 , 但是不像是 , 这些档案是二进制的且 无格式也有可能会改变, 在你 一个 函数时 Xcode 就是利用这些档案去定位其所属的 module.
尽管这些都是二进制文件, 但他们仍是一种叫 的结构, 正因如此, 我们能用 取得相关信息. - : 虽然他被 标注成 , 但他其实是一个
- : 文件
由于有 的存在, 我们在判断一个库到底是静态库还是动态库就有了麻烦, 因为一个 既可以是动态库也可以是静态库, 依赖于其内部的文件类型, 而 中的二进制文件有可能有后缀, 也有可能没有后缀.

为了区分其类型我们可以借助, 或者是在 Xcode 的 -> 中查找 选项.

我们可以在一个项目中使用一部分动态库, 再使用一部分静态库, 如果涉及到第三方库与库之间的依赖关系时, 那么遵守如下原则:
-
讯享网
静态库可以依赖静态库 -
动态库可以依赖动态库 -
讯享网
动态库不能依赖静态库! 动态库不能依赖静态库是因为静态库不需要在运行时再次加载, 如果多个动态库依赖同一个静态库, 会出现多个静态库的拷贝, 而这些拷贝本身只是对于内存空间的消耗.
默认情况下, 当我们在 文件中写下:
的时候, cocoapods 默认会使用静态库, 我们可以在 文件夹中看到编译出的 文件

在项目的 中, 我们可以看到静态库被编译进入可执行文件 ( 文件), 导致文件大小为 14.9M

cocoapods 提供了 选项让我们可以以 的形式导入第三方库, cocoapods 默认我们开启了此选项后在 文件夹中放的是动态库, 因此我们可以在 中加入 来达到引入动态库的效果, 如下:
然后经过 之后, 结果如下:


cocoapods 编译生成的结果文件已经变为了 文件夹
再来看项目结果文件 :

我们可以看到
-
由于动态库未被编译进入可执行文件 ( 文件), 导致文件大小减小到 14.8M -
讯享网
多了一个 文件夹用于存放 文件
在 动静态库的混用 中我们我们知道动态库不能依赖静态库, 因此在实际项目中会有一种需要特别注意的情况: 如果项目中有一个库必须是静态库时, 那么其整个依赖链路上的所有库都必须以静态库被引入, 如下图:

在 为静态库的情况下, 整个依赖链路上的所有库( 与)都必须以静态库形式被项目依赖
这时我们需要使用 cocoapods 在版本 1.5 之后推出的新功能: . 这个命令使用在库的 文件中, 用来指定本库作为静态库被其他项目作为 包含静态库的 文件 引入. 这样我们就可以在开发库的时候手动指定本库被以静态库还是动态库形式被引入了.
在 iOS app 启动时系统会查找我们所依赖的所有动态库并加载, 这降低了我们 App 的启动速度, 那么可不可以将动态库的调用时间延迟到 app 运行时? 答案是不能!
不能动态加载动态库的原因是系统的限制. 查看苹果的 API 文档, 会发现有一个方法提供了加载可执行文件的功能, 那就是 的 方法 (底层实现为 函数), 如下所示:

然而, 这个方法的使用是有前提的. 那就是库和 app 的签名必需一致. iOS 可能是出于安全考虑, 在加载可执行代码前, 需要校验签名. 方法的内部实现是调用了 , 而真机的 内部还会调用 先校验签名. 如果库不是事先打包进 app(打包进 app 的话会与 app 有相同签名), 就会报签名错误, 从而加载不成功. 如下图所示:


因此动态加载加载动态库在模拟器上可以实现, 但是真机上不能运行
那么肯定有人会问, 既然无法加载成功, 苹果为什么要提供这个方法? 答案是, 虽然 iOS 无法使用, 但是 Mac OS 可以使用, 很明显这个方法目前是提供给 Mac OS 使用的. 如果以后系统放开签名校验, 那么 iOS 中也就可以动态加载了.
- 动态库不能依赖静态库!
- 对于 项目, 提供了 的支持, 通过 选项控制. 需要注意的是如果使用此选项那么所有依赖的 都会以 包裹的动态库类型引入, 如果想让某些 使用动态库引入, 某些 使用静态库引入, 那么请看下面
- 是典型的静态库, 在 -> -> -> 中的 即可新建 静态库
- 可以做成静态库, 也可以做成动态库, 在工程中修改某个 target 的 的 即可. 在 -> -> -> 中的 的 即可新建 静态库
- 是纯二进制文件, 中除了有二进制文件之外还可以有资源文件. 文件不能直接使用, 至少还要有 文件配合, 文件可以直接使用, 因为本身包含了 和其他文件
- + + = , 建议使用
- 静态库与动态库区别:
-
静态库: 链接时完整地拷贝至可执行文件中, 被多个依赖多次使用就会有多份冗余拷贝. </li><li> 动态库: 链接时不复制, 程序运行时由系统动态加载到内存, 供程序调用, 系统只加载一次, 多个程序共用, 节省内存.(这个优点是针对系统动态库来说的, 比如 ) </li></ul><ul><li>系统的 不需要拷贝到目标程序中, 我们自己做出来的 哪怕是动态的, 最后也还是要拷贝到 App 中, 因此苹果又把这种 称为 .<br></li><li>当不想发布代码的时候, 也可以使用 发布 , 提供了 选项来使用第三方 </li><li>如果想通过 制作一个静态库被其他项目依赖, 那么可以在 pod 的 文件中使用 命令, 这个命令会使 pod 变为由 包裹的静态库 (即使项目的 中使用了 时使用 也会以静态库使用), 这在解决 的问题上非常有用.<br></li><li>Mach-O 格式的几种文件和 iOS 工程 Build Settings 里面的配置项是对应的.<br></li><li>系统动态库和自己编译的动态库本质上是一样的, 只是使用方式不一样. 自己编译的动态库由于签名校验限制, 只能当作静态库一样使用; 系统的动态库不受签名校验限制, 可以动态加载.<br></li><li> 与 都是库 (Library), 库都是二进制的, 看不到源码的, 只能看到头文件, Cocoapods 方式集成的可以看到源码是因为将源码放在一个新构建的 工程中了, Pods 的主目标是一个 , 这个 target 依赖了我们所有导入的第三方库, 然后主项目对 Pods 工程中的这个 的生成 进行依赖, 形成了我们好像直接可以使用第三方库源码的错觉 himg </li></ul><p>本文作者 Hanley Lee, 首发于 闪耀旅途, 如果对本文比较认可, 欢迎 Follow</p><ul><li>年轻人, 听说你想使用 Framework - 基础观念 - Xcode 6 制作动态及静态 Framework
- How to Use a Third Party Framework in a Private CocoaPod
- iOS 开发中的『库』(一)
- 通过dylib实现iOS运行时Native代码注入(动态调试)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/193959.html