库
- 库是共享代码的一种方式;
- 从本质上来说库是一种可执行代码的二进制格式,可以被载入到内存中执行;
- 库可分为
静态库
与动态库
,在iOS中静态库有.a
与framework
两种形式,动态库有.dylib
与framework
两种形式,后来.dylib
被替换成.tbd
形式;
静态库
- 静态库在程序
编译时
会被拷贝到目标程序中,运行时
不能再修改静态库,同一个静态库在不同程序中使用时,每个程序中都会拷贝导入一次,造成多份冗余拷贝,浪费内存空间;
动态库
动态库在程序
编译时
只链接不拷贝到目标程序,运行时
由系统动态加载到内存,供程序调用,系统只会加载一次,多个程序可以共用,节省内存;注意动态库不会被拷贝到目标程序中,所以程序体积会小很多,系统的框架UIKit,Foundation等都属于动态库,但苹果不让使用自定义的动态库,若使用则审核无法通过,系统的
.framework
是动态库,我们自己建立的.framework
是静态库,所以说framework既可以是静态库,又可以是动态库;
.a与.framework之间的区别
-
.a
是一个纯二进制文件,其不能直接使用,需要有.h文件配合才能使用; -
.framework
中除了二进制文件之外还有资源文件,其包括.a + .h + sourceFile = .framework, .framework是可以直接使用的;
为什么要使用静态库?
- 方便共享代码,便于合理使用;
- 实现iOS程序的模块化,可以将固定的业务模块化成静态库;
- 向别人分享你的代码库,但是不想让别人看到你代码的实现,开发第三方SDK的需要;
iOS移动设备的CPU架构
- 通常,我们知道电脑的CPU架构有X86和X64等,但是手机的主流CPU架构是ARM架构,因为采用ARM架构的CPU是一种微处理器,这种处理器功耗低,体积小,更适合手机使用,iPhone的CPU也是如此;
- iOS设备常见的架构如下所示,分为模拟器与真机两大类:
.a静态库的制作与使用
本人使用的是Xcode12.4;
-
第一步:打开Xcode,新建一个
Static Library
工程,如下所示:
静态工程名称为
MyCategory
-
第二步:
MyCategory
工程创建成功后,默认会生成MyCategory.h
与MyCategory.m
两个文件,删除MyCategory.m
,保留MyCategory.h
,然后在MyCategory.h
文件中导入自己代码文件的所有头文件,如下所示:
第三步:静态工程配置,为了能支持真机与模拟器,做以下的工程配置:
-
针对Build Setting -> Architectures 即设置架构选项,我们来做以下详细的阐述:
-
Architectures
:默认设置为arm64与armv7架构是针对真机的,说明苹果遗弃了armv7s的真机架构,如果加上armv7s需要我们手动添加
; -
Build Active Architectures Only
:表示编译文件是否仅仅只支持当前选中的设备
所包含的架构;默认情况下Debug模式下为YES,Release模式下为NO; -
Excluded Architectures
:删除指定的架构;
-
现做如下设置,注意我选择的
Release模式
,然后进行编译;
- 真机生成的.a文件支持
arm64
与armv7
两种架构,如下所示:
- 然后切换到iOS模拟器,我选择的是iPhone8 Plus,再编译,生成的.a文件支持
arm64
,x86_64
与i386
三种架构,如下所示:
模拟器居然也支持
arm64
架构,觉得有点不可思议了,从网上查相关资料说是Xcode12才会支持,这就为真机与模拟器.a文件的合并,带来隐患,下面内容有提到;-
关于
Architectures
的其他选项保持不变,手动输入真机架构,如下所示:
真机生成的.a文件支持arm64,armv7 与 armv7s三种架构,如下所示:
- 设置.a文件支持的最低系统版本 iOS Deployment Target iOS 9.0
- 第四步:手动导入自己代码的所有.h文件,如下所示:
- 第五步:编译前检查一下是
debug模式
还是release模式
,我们需要选择release模式;
分debug和release模式:
Debug-iphoneos
文件夹里面的东西是用在真机
上的
Debug-iphonesimulator
文件夹里面的东西是用在模拟器上
的
如果 Scheme 是 Release 模式,生成的文件夹就以 Release 开头;
如下所示:
- 第六步:编译 Command + B,首先选择真机状态下进行编译,然后选择模拟器状态载进行编译,最后会生成
libMyCategory.a
静态文件,如下所示:
会看到
Release-iphoneos
与Release-iphonesimulator
两个文件夹,分别为真机与模拟器的静态库文件;第七步:静态库文件合并,即将
Release-iphoneos
与Release-iphonesimulator
两个文件夹下的.a文件合并称一个.a,以便同时支持真机和模拟器,合并后的.a大小大约是未合并.a文件的2倍左右;cd 到
Products
文件夹下,执行lipo -create Release-iphoneos/libMyCategory.a Release-iphonesimulator/libMyCategory.a -output CategoryLib.a
,出现报错,如下所示:
- 其原因在于Xcode12 编译的模拟器库新增支持架构arm64,需将模拟器的
arm64
给排除出去即可,工程配置如下:
- 然后在真机与模拟器状态下,重新编译,最后cd 到
Products
文件夹下,执行lipo -create Release-iphoneos/libMyCategory.a Release-iphonesimulator/libMyCategory.a -output CategoryLib.a
,在Products
文件夹下会生成一个CategoryLib.a
静态库文件,如下所示:
- 执行
file CategoryLib.a
可查看其文件类型及支持的架构信息,如下所示:
- 第八步:.a静态库的导入使用,新建一个工程
Test_AProject
,然后导入上面制作的.a静态库文件CategoryLib.a
,在桌面上新建一个文件夹
MyLib
,然后将真机的include
文件夹与合并后的.a文件复制到MyLib
文件夹中;-
将
MyLib
文件夹拖入Test_AProject
工程中,如下所示:
-
需要设置
Test_AProject
工程的配置,如下所示:
在
bulidPhase
-->Link Binary with Libraries
中必须导入.a文件
- 然后调用静态库
CategoryLib.a
中的函数方法,最后调用成功!!!
参考文章:
https://blog.csdn.net/shifang07/category_9287774.html?spm=1001.2014.3001.5482