静态库和动态库
简介
什么是库?
- 库是程序代码的集合,是共享程序代码的一种方式
-
根据源代码的公开情况,库可以分为2种类型
- 开源库
- 公开源代码,能看到具体实现
- 比如SDWebImage、AFNetworking
- 闭源库
- 不公开源代码,是经过编译后的二进制文件,看不到具体实现
- 主要分为:静态库、动态库
- 开源库
-
为什么制作闭源库
- 国内的企业,掌握有核心技术,同时是又希望更多的程序员来使用其技术,因此采用"闭源"的方式开发使用 例如:百度地图,友盟,JPush等
- 在企业开发中,一些核心技术或者常用框架,出于安全性和稳定性的考虑,也会提供静态库给程序员使用
- 静态库与动态库
- 静态库和动态库的存在形式
- 静态库:.a 和 .framework
- 动态库:.dylib(Xcode7.0之前) .tbd[Xcode7以后] 和 .framework
- 静态库和动态库在使用上的区别
- 静态库:链接时,静态库会被完整地复制到可执行文件中,被多个应用使用就有多份冗余拷贝(左图所示)
- 动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存(右图所示)
-
-
- 3.需要注意的是:项目中如果使用了自制的动态库,在Xcode6之前不能被上传到AppStore,Xcode6以后可以上传AppStore
-
静态库
静态库的特点
.a +.h
制作静态库简单演练
-
步骤
-
- 新建一个Tools的静态库项目
-
创建一个类方法,实现简单的加法
- Tools.h文件
+ (double) sumNum1:(double) x andNum2:(double) y;
- Tools.m文件
+ (double)sumNum1:(double)x andNum2:(double)y { return x + y; }
- 编译: 注意,在编译静态库时,需要编译两个版本 ->
真机(arm)
|模拟器(i386)
- 查看文件导航栏->Product->libTools.a文件,如果为
红色
表示没有生成.a文件,如果是黑色
表示生成了.a文件 - 仅仅编译模拟器不会生成.a,需要在真机下编译才能生成.a文件
- 选中.a文件->右击->showFinder 如图,生成两个.a文件,一个用于真机,一个用于模拟器
- 查看文件导航栏->Product->libTools.a文件,如果为
-
测试生成的静态库
-
新建ToolsTest的iOS项目
- 将编译生成的模拟器的.a + .h拖到项目中使用
- 在ViewController.m导入Tools.h文件
- 使用调用类方法 + (double) sumNum1:(double) x andNum2:(double) y;
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { double rs = [Tools sumNum1:10.4 andNum2:20.5]; NSLog(@"%lf",rs); }
输出结果:30.9
-
带有资源的静态库
-
步骤:简单静态库的基础上
- 创建一个资源工具类CZResourceTools
- 导入图片资源
-
提供获取图片资源的方法
+ (UIImage *) logoOfItcast; + (UIImage *) logoOfItheima; + (UIImage *) lufei;
-
编译,编译后的
include
文件夹中没有我们刚刚添加的CZResourceTools.h文件,解决方法项目
->TARGETS
->Build Phases
->Copy Files
->添加
需要头文件 如图 -
- 测试,修改测试测试项目
- 删除之前导入.h+.a文件
- 导入新生成的 .h + .a 文件
- 在ViewController导入CZResourceTools.h
- 实现如下代码
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UIImage *image = [CZResourceTools logoOfItcast]; NSLog(@"%@",image); }
5.点击屏幕输出内容为:
ToolsTest[2260:252976] (null)
这是因为.a 文件中仅仅包含二进制的代码,不包含资源文件,如果你需要是资源还要把资源导入 6.导入静态库中使用的资,运行点击屏幕输出内容:
ToolsTest[2276:256084] <UIImage: 0x7fbf7bc25b30>, {202, 76}
这样使用静态库非常麻烦,并且与当前项目的资源混杂在一起,容易丢失
-
当静态库中包含一些固定的资源文件时候最好打包一个bundle,方便其他人使用
1. 新建一个文件夹命名为:resource(此处你可以根据需要随意命名)
- 把需要的资源拖入当前文件夹
- 为给文件夹添加后缀.bundle
-
修改资源加载路径,文件前面添加包路径
+ (UIImage *) logoOfItcast { return [UIImage imageNamed:@"resource.bundle/logo_itcast.png"]; } + (UIImage *) logoOfItheima{ return [UIImage imageNamed:@"resource.bundle/logo_itheima.png"]; } + (UIImage *) lufei{ return [UIImage imageNamed:@"resource.bundle/logo_itheima.png"]; }
- 编译,测试, 替换ToolsTest项目中
.a
,.h
文件并导入resource.bundle
文件即可.
- 编译,测试, 替换ToolsTest项目中
-
运行,点击屏幕,输出内容:
ToolsTest[2276:256084] <UIImage: 0x7fbf7bc25b30>, {202, 76}
静态库的版本
静态库的四个版本
1. 真机-Debug版本
2. 真机-Release版本
3. 模拟器-Debug版本
4. 模拟器-Release版本
调试版本(Debug版本) VS 发布版本(Release版本)
- 调试版
- 调试版本会包含完整的符号信息,以方便调试
- 调试版本不会对代码进行优化
- 发布版
- 发布版本不会包含完整的符号信息
- 发布版本的执行代码是进行过优化的
- 发布版本的大小会比调试版本的略小
- 在执行速度方面,调试版本会更快些,但不意味着会有显著的提升
如何生成发布版静态库
- 默认情况下生成的版本都是
调试版
静态库,如何生成发布版
的静态呢? -
步骤:
- 再编译静态库(模拟与真机上都要),生成发布版静态库
- 发布版真机版 Release-iphoneos
- 发布版模拟器版 Release-iphonesimulator
静态库与CPU架构
- 把模拟器调整到iphone5,编译报错
- 错误如图所示
- 错误原因:导入的.a文件,不支持模拟iPhone5的CPU架构i386
- CPU架构说明:
1. 模拟器CPU架构: 1. iPhone4s,iPhone5->`i366` 2. iPhone5s以后->`x86_64` 2. 真机CPU架构: 1. iPhone3gs-->iPhone4s : `armv7` 2. iPhone5-->iPhone5c : `armv7s` 3. iPhone5s-->iPhone6plus : `arm64`
- 通过终端命令查看.a文件所支持的CUP架构
lipo -info 静态库.a
- not a fat file : 说明该.a文件不支持多重架构
- architecture: x86_64 : 说明该.a 支持x86_64架构
- 如何让生成.a文件支持i386:
Build Settings
-->Build Active Architecture Only
-->NO
,如图:- 重新编译:
- product->clear
- 模拟器下编译
- 真机下编译
- 再次查看模拟所支持的架构
- 合并静态库
- 通过终端命令可以将静态库进行合并:
lipo -create 静态库1.a 静态库2.a -output 新静态库的名称.a
如图: - 查看生成后的静态库 如图:
- 通过终端命令可以将静态库进行合并:
- 测试生成后的静态库
- 把测试项目中原来的的.a文件替换成为新的.a文件
- 分别在4s,6s和真机下运行测试项目
制作framework 使用framework制作动态库
-
使用framework制作动态库
- 创建一个framework项目,
- 注意:framework项目中不可以包含特殊字符
- 创建一个名称为
预习01-framework制作
编译,报错如下 - 删除原来项目重新创建一个
MakeFrawork
项目 - 一个framework默认就有一个与项目同名的主头文件,该头文件用于包含其他的头文件,当用户使用这个framework的时候,只需要导入主头文件即可
- 创建一个名称为
- 注意:framework项目中不可以包含特殊字符
- 创建CZTools的工具类
- 实现一个简单的类方法
-
让头文件暴露在外部
- 设置支持多种架构(与静态库相同)
- 编译framework(需要模拟器和真机上都进行编译)
-
测试framework
- 创建测试项目
FrameworkTest
- 导入
MakeFramework.framework
- 在
ViewController.m
中导入头文件- 格式:
#import <MakeFramework/MakeFramework.h>
- 格式:
-
调用framework中的方法
#import <MakeFramework/MakeFramework.h> @interface ViewController () @end @implementation ViewController - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { int rs = [CZTools sumOfNum1:10 andNum2:20]; NSLog(@"%d",rs); } @end
-
运行测试项目,报错:
错误原因:默认情况下framework是动态库,使用的时候还需要添加到
embedded binaries
(被嵌入的二进制)- 第一步:target->general->embedded binaries->
+
- 第二步:选择framework ->
add
在再次运行项目,点击屏幕打印出
30
注意: 项目中如果使用了自制的动态库,在Xcode6之前不能被上传到.AppStore,Xcode6以后可以上传AppStore
- 第一步:target->general->embedded binaries->
- 创建测试项目
- 创建一个framework项目,
-
使用framework也可以是静态库的形式,
- 只需要简单修改
target
->Bulid Setting
->Mach-O Type
->Statuc Library
- 测试framework的静态库,只需要把framework文件拖入到项目中即可!
-
其实可以framework理解为是.a 文件与.h文件的合体,所以在使用上framework比.a文件更加方便,现在很多第三方框架使用的都是framework的形式.
- 带有资源的framework与可测试的framework与静态库相同,此处不再赘述.