库(Library)

是一段编译好的二进制代码,加上头文件就能够直接链接(Link)运用了

库的品种有两种: 静态库和动态库

静态库

静态库即静态链接库

  • 一组方针文件(object file, 以 .o 为后缀)的集合, 即很多方针文件经过压缩打包后形成的文件
  • 格局
    • Windows 的 .lib
    • Linux 和 iOS 下的 .a
    • iOS独有的.framework。
  • 优势
    • 供给的是方针文件, 所以不需求从头编译, 只需求链接即可
    • 加载 App 速度更快, 因为在编译时已经进行了链接, 发动时不需求进行二次查找发动
  • 缺陷:
    • 浪费内存和磁盘空间,模块更新困难

动态库

动态链接库, Dynamic Libraries, 也称作 Shared Library

  • 动态库并不会在编译时编译到app中, app只会存储指向动态库的引用。比及程序运转时,动态库才会被真实加载进来。
  • 依据载入时间 (load time)将动态库分为两种:
    • 动态链接库: 经过dyld程序在app发动时将加载动态库
    • 动态加载库: app发动后再运用dlopen来懒加载动态库(iOS不支持, MacOS支持)
  • 格局
    • MacOS/iOS: .tbd, .dylib 或封装成 .framework, xcframework
    • Linux: .so
    • Windows: .dll
  • 优势 动态库不需求在编译时置入 app 中, 因而理论上app体积会更小, 并且能够做到动态库内容不需求从头编译即可获得最新功用
  • 缺陷:

会导致一些性能丢失。可是能够优化,比如推迟绑定(Lazy Binding)技能

  • 能够前往MacOS体系途径 /usr/lib 文件夹查看体系的动态库.

iOS静态库和动态库详解

Framework

  • 一种打包办法,其实便是文件夹, 将库的二进制文件,头文件和有关的资源文件(图片, Xibs, 动态库, 静态库, 文档)打包到一同,便利办理和分发。

组成

  • Headers: 包括了 Framework 对外公开的头文件, Swift 并不会用到这些 Headers

  • swiftmodule:是编译器对代码分析之后,将可露出的类或办法写在其间, 相当于Swift库的头文件. 是二进制且内容随时会改变

iOS静态库和动态库详解

  • executable(静态库/动态库)
  • bundle 文件/图片
  • xibs

Embedded Framework

  • Framework 和体系的 UIKit.Framework 仍是有很大区别。体系的 Framework 不需求拷⻉到方针程序中,咱们自己做出来的 Framework 哪怕是动态的,最终也仍是要拷⻉到 App 中,因而把这种 Framework 称为 Embedded Framework
  • 开发中运用的动态库会被放入到ipa下的framework目录下,基于沙盒运转。
  • 不同的App运用相同的动态库,并不会只在体系中存在一份。而是会在多个App中各自打包、签名、加载一份。

动静态库的混用

咱们能够在一个项目中运用一部分动态库, 再运用一部分静态库, 假如涉及到第三方库与库之间的依靠联系时, 那么恪守如下原则:

  • 静态库能够依靠静态库
  • 动态库能够依靠动态库
  • 静态库能够依靠动态库
  • 动态库不能依靠静态库! 动态库不能依靠静态库是因为静态库不需求在运转时再次加载, 假如多个动态库依靠同一个静态库, 会呈现多个静态库的复制, 而这些复制自身仅仅关于内存空间的耗费

假如项目中有一个库必须是静态库时, 那么其整个依靠链路上的一切库都必须以静态库被引进, 如下图:

iOS静态库和动态库详解
在 库 4 为静态库的情况下, 整个依靠链路上的一切库(库 5 与库 3)都必须以静态库方式被项目依靠

tdb

  • tbd全称是text-based stub libraries,本质上便是一个YAML描述的文本文 件。
  • 他的作用是用于记录动态库的一些信息,包括导出的符号、动态库的架构信息、动 态库的依靠信息
  • 用于避免在真机开发过程中直接运用传统的dylib。
  • 关于真机来说,由于动态库都是在设备上,在Xcode上运用基于tbd格局的伪 framework能够大大减少Xcode的巨细。

XCFramework

是苹果官方推荐的、支持的,能够更便利的表示一个多个渠道和架构的分发二进制库的格局。 需求Xcode11以上支持。 是为更好的支持Mac Catalyst和ARM芯片的macOS。 专⻔在2019年提出的framework的另一种先进格局。

和传统的framework比较:

  1. 能够用单个.xcframework文件供给多个渠道的分发二进制文件;
  2. 与Fat Header比较,能够按照渠道区分,能够包括相同架构的不同渠道的文件;
  3. 在运用时,不需求再经过脚本去剥离不需求的架构体系。

创立动态库静态库

指令

  • 创立静态库 libtool -static
  • 创立动态库 libtool -dynamiclib

XCode

创立 framework和静态库

iOS静态库和动态库详解
创立完成后, 选中Mach-O Type, 调整Dynamic LibraryStatic Library

iOS静态库和动态库详解

Cocoaspods 库装备

  • Cocoapods podfile 默认是结构静态库
  • use_frameworks! 选项让咱们能够以, .framework 和动态库方式引进
  • s.static_frameworks = true 指定本库作为静态库引进.
platform :ios, '11.0'
source 'https://cdn.cocoapods.org/'
use_frameworks!
target 'Test' do
  pod 'AFNetworking'
end

为什么动态库不能动态加载

在 iOS app 发动时体系会查找咱们所依靠的一切动态库并加载, 这降低了咱们 App 的发动速度, 那么可不能够将动态库的调用时间推迟到 app 运转时? 答案是不能!

不能动态加载动态库的原因是iOS体系的约束. 查看苹果的 API 文档, 会发现有一个办法供给了加载可执行文件的功用, 那便是 NSBundle 的 load 办法 (底层实现为 dlopen 函数), 如下所示:

iOS静态库和动态库详解

  • iOS 出于安全考虑, 在加载可执行代码前, 需求校验签名.
  • load 办法的内部实现是调用了 dlopen, 而真机的 dlopen 内部还会调用dlopen_preflight 先校验签名. 假如库不是事先打包进 app(打包进 app 的话会与 app 有相同签名), 就会报签名过错(Signature error), 从而加载不成功.
  • 因而动态加载库在模拟器上能够实现, 可是真机上不能运转
  • 一切现在只能在 Mac OS 上运用. 假如以后体系铺开签名校验, 那么 iOS 中也就能够动态加载了

参考文章

iOS 中的静态库与动态库 – 知乎 (zhihu.com)