.a & .framework
1.库?
库是代码的集合、共享代码的一种方式。分为:
- 开源库:源代码公开,能看到具体的实现。(如SD、AF)
- 闭源库:源码不公开,是经过编译后的二进制文件,看不到具体实现。
其中,闭源库有两种形式:
- 静态库:.a 和 .framework
- 动态库:.dylib 和 .framework
问:framework 为啥即是静态库又是动态库?
答:系统提供的.framework是动态库,我们自定义的是静态库。
系统提供的有UIKit.framework等,自定义的包括AFN.framework等。
在早期,很多应用基于.framework动态库实现热更新,而苹果不允许这种行为,它禁止使用自定义动态库的应用上架。我们自己建的.framework中 Mach-O Type 需要设置为 Static Library,即静态库。现在苹果已经允许我们将.framework设置成动态库,只是苹果会在集成自定义动态库的应用上架时,再经过一次AppStore的签名,防止在线更新动态库。当然,自建的.dylib还是不允许。
2.静态库
静态库在编译阶段进行链接,成为可执行文件的一部分,可能会增加包体大小。
ps: 使用静态库时,设置Dead Code Stripping等进行优化,包体可能会比framework小。
多个应用使用相同的静态库时,各应用都会完整地复制一份到可执行文件中,内存中有冗余。
因为可执行文件变大,启动时需加载的内容变多,可能会导致应用启动变慢。
3.动态库
动态库是在启动阶段进行链接,不包含在应用的可执行文件中,可有效减小包体大小。
多个应用使用相同的动态库时,系统只会在内存中加载一次,多个应用共享,节省内存。
系统的动态库可在应用间共享;用户自定义的动态库不行,只能在主包和扩展中共享。
4.封装格式
.a与.framework都是二进制文件的封装格式。
1.静态库.a
.m等文件在编译后会变成.o文件,而.a是多个.o的集合。
.o是Mach-O文件类型,每个.o都包含 Mach header、Segment、section、Blob。
多个.o中可能有相同的 Mach header 等冗余,所以包体会大于动态库的framework。
2.动态库.framework
.framework可将库的代码与资源文件打包到一起,方便管理和分发。
1 |
|
.a是一个纯二进制文件,.framework 中除了有二进制文件之外还有资源文件。
.a不能直接使用,至少要有.h文件配合,.framework 文件可以直接使用。
framework中所有.o文件的前三段合并到了一起,只有一个公共的 Mach header、Segment、Section,从而优化了.a中每个.o都含这些头块区的冗余问题,减小了包体。
自己建的 framework 虽然叫动态库,但它的实质却是 Embedded Framework。
- 基于沙盒,最终打包到ipa的/framework目录(包括pods),与其他应用隔离。
- 需要签名,即使跟别的应用同名,也不共享。
- 可以上架,但不允许热更新(AppStore会再一次签名)。
不同应用使用同名自定义动态库framework,内存中并非只加载一份,而是分别打包、签名、加载各自的。它只是保留了与系统动态库相同的链接方式,但是仅能在各自的应用中使用。
5.制作.a
- 新建 Cocoa Touch Static Library 工程,编写逻辑代码。
1 |
|
- Targets->Build Settings 参数设置:
1 |
|
- Targets->Build Phases 参数设置:
1 |
|
- Run 修改 scheme
1 |
|
- 编译生成静态库.a文件:
1 |
|
- 合成通用版的静态库.a文件
1 |
|
- 测试自己制作的静态库文件
将.h 以及上步导出的.a文件导入自己的工程中,调用.h 中的接口。
1 |
|
6.制作.framework
- 新建 Cocoa Touch Framework 工程,编写逻辑代码。
1 |
|
- 更改参数:
1 |
|
- 设置需要暴露的头文件
1 |
|
- 在新建项目时,自动生成的xxx.h文件里将要暴露的头文件 import 进来。
1 |
|
- Edit Scheme
1 |
|
- 编译 framework
1 |
|
- 合成通用 framework
1 |
|
这一步可能会报错,但依然会生成一个xx.lipo
文件,将其后缀去掉并复制到/xx.framework
(真机.framework文件路径)下,替换目录中原有的framework。
- 测试 framework
将上一步中替换完成的xx.framework 复制到新的工程里,导入头文件:
1 |
|