库(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 文件夹查看体系的动态库.
Framework
- 一种打包办法,其实便是文件夹, 将库的二进制文件,头文件和有关的资源文件(图片, Xibs, 动态库, 静态库, 文档)打包到一同,便利办理和分发。
组成
-
Headers
: 包括了 Framework 对外公开的头文件, Swift 并不会用到这些 Headers -
swiftmodule
:是编译器对代码分析之后,将可露出的类或办法写在其间, 相当于Swift库的头文件. 是二进制且内容随时会改变
- executable(静态库/动态库)
- bundle 文件/图片
- xibs
- …
Embedded Framework
- Framework 和体系的 UIKit.Framework 仍是有很大区别。体系的 Framework 不需求拷⻉到方针程序中,咱们自己做出来的 Framework 哪怕是动态的,最终也仍是要
拷⻉到 App 中
,因而把这种 Framework 称为Embedded Framework
。 - 开发中运用的动态库会被放入到ipa下的framework目录下,基于沙盒运转。
- 不同的App运用相同的动态库,并不会只在体系中存在一份。而是会在多个App中
各自打包、签名、加载
一份。
动静态库的混用
咱们能够在一个项目中运用一部分动态库, 再运用一部分静态库, 假如涉及到第三方库与库之间的依靠联系时, 那么恪守如下原则:
- 静态库能够依靠静态库
- 动态库能够依靠动态库
- 静态库能够依靠动态库
-
动态库不能依靠静态库
! 动态库不能依靠静态库是因为静态库不需求在运转时再次加载, 假如多个动态库依靠同一个静态库, 会呈现多个静态库的复制, 而这些复制自身仅仅关于内存空间的耗费
假如项目中有一个库必须是静态库时, 那么其整个依靠链路上的一切库都必须以静态库被引进, 如下图:
在 库 4 为静态库的情况下, 整个依靠链路上的一切库(库 5 与库 3)都必须以静态库方式被项目依靠
tdb
- tbd全称是text-based stub libraries,本质上便是一个YAML描述的文本文 件。
- 他的作用是用于记录动态库的一些信息,包括导出的符号、动态库的架构信息、动 态库的依靠信息
- 用于避免在真机开发过程中直接运用传统的dylib。
- 关于真机来说,由于动态库都是在设备上,在Xcode上运用基于tbd格局的伪 framework能够大大减少Xcode的巨细。
XCFramework
是苹果官方推荐的、支持的,能够更便利的表示一个多个渠道和架构的分发二进制库的格局。 需求Xcode11以上支持。 是为更好的支持Mac Catalyst和ARM芯片的macOS。 专⻔在2019年提出的framework的另一种先进格局。
和传统的framework比较:
- 能够用单个.xcframework文件供给
多个渠道
的分发二进制文件; - 与Fat Header比较,能够按照渠道区分,能够包括相同架构的不同渠道的文件;
- 在运用时,
不需求再经过脚本去剥离
不需求的架构体系。
创立动态库静态库
指令
- 创立静态库 libtool -static
- 创立动态库 libtool -dynamiclib
XCode
创立 framework和静态库
创立完成后, 选中Mach-O Type
, 调整Dynamic Library
和 Static Library
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 出于安全考虑, 在加载可执行代码前, 需求
校验签名
. - load 办法的内部实现是调用了
dlopen
, 而真机的 dlopen
内部还会调用dlopen_preflight
先校验签名. 假如库不是事先打包进 app(打包进 app 的话会与 app 有相同签名
), 就会报签名过错
(Signature error), 从而加载不成功. - 因而动态加载库在模拟器上能够实现, 可是真机上不能运转
- 一切现在只能在 Mac OS 上运用. 假如以后体系铺开签名校验, 那么 iOS 中也就能够动态加载了
参考文章
iOS 中的静态库与动态库 – 知乎 (zhihu.com)