基本知识:
1. 库类别
- 静态库(.a 和.framework)
- 动态库(.liby和.framework)
2.静态库和动态库的区别
2.1静态库
- 平时我们用的第三方SDK基本上都是静态库。
- 静态库在项目编译时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。
- 静态库很大的一个优点是减少耦合性,因为静态库中是不可以包含其他静态库的,使用的时候要另外导入它的依赖库,最大限度的保证了每一个静态库都是独立的,不会重复引用。
- 静态库有.a 和 .framework两种形式。
2.2动态库
- iOS平时使用的系统库基本是动态库,比如使用频率最高的UIKit.framework和Fundation.framework。
- 动态库在程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。
- 动态库在制作的时候可以直接包含静态库,也能自动link所需要的依赖库。
- 动态库有.dylib/.tbd 、.framework两种形式。
- 苹果禁止iOS开发中使用动态库
3.版本
- 真机-Debug版本
- 真机-Release版本
- 模拟器-Debug版本
- 模拟器-Release版本
区别
3.1 Debug
- 含完整的符号信息,以方便调试
- 不会对代码进行优化
3.2 Release
- 不会包含完整的符号信息
- 的执行代码是进行过优化的
- 的大小会比Debug版本的略小
- 在执行速度方面,Release版本会更快些(但不意味着会有显著的提升)
基本操作:.a静态库制作
环境
Xcode9.1
iTerm终端
1. 新建静态库工程
Create a New Xcode project -> Framework&Library -> Cocoa Touch Static Library
文件结构如下:
2. 配置工程环境
2.1配置最低支持版本
2.2设置适配所有模拟器架构重要
project -> buildSeting -> Build Active Architecture Only 设为NO
3. 新建公开的文件
3.1新建一个名为“testTool 文件” 公开一个方法“testLog”
3.2添加公开文件
3.2.1 点击“+” 新增”Header Phase”
3.2.2 添加文件到 project
3.2.3 拖拽.h到 public
最终结果如下:
4. 生成.a文件
此处注意需要生成4个
4.1修改环境
这里可以选择 Debug 和 Release 环境
4.2选择模拟器+Debug 环境+“cmd+R”生成.a
此处注意需要生成4个
如此类推打出四种.a
- 真机-Debug版本
- 真机-Release版本
- 模拟器-Debug版本
- 模拟器-Release版本
最终生成结果
4.3合并 debug 两个包和 release 两个包
注意:这里的合并指的是 1.debug 下真机+模拟器合并 2.release 下真机+模拟器合并
4.3.1将4个.a文件拷贝到单独文件夹
4.3.2 合并
打开终端
命令规则
lipo -create+空格+模拟器Debug路径+空格+模拟器Release路径+空格-output+空格+输出路径+输出名字(可自定义)
例如:
lipo -create /Users/fujia/Desktop/a/libStaticWork-Debug-iphoneos.a /Users/fujia/Desktop/a/libStaticWork-Debug-iphonesimulator.a -output /Users/fujia/Desktop/a/libStaticWork-Debug.a
- 1
- 2
- 3
- 4
标注出是自己起名
同理 release 也是如此 最后生成两个文件
5.使用方法
5.1新建一个新工程
**5.2引入文件
5.2.1引入libStaticWork-Debug.a和libStaticWork-Release.a
5.2.2引入 include 文件
在之前的静态库文件找到任意的生成文件 引入 include 文件
最后引入结果如下
5.3调用以及结果
基本操作:.framework静态库制作
1.新建 framework 工程
2.新建文件类
3.修改工程文件配置
build setting ->搜索 mach -> 修改 mach -O Type ->static Library
4.引入其他第三方库(如果有的话)
⚠️注意:导入第三方静态库的时候不要选择添加到target中
5.暴露头文件
拖拽文件到这里
6.生成 .framework
6.1修改环境
这里可以选择 Debug 和 Release 环境
6.2选择模拟器+Debug 环境+“cmd+R”生成.a
此处注意需要生成4个
如此类推打出四种.a
- 真机-Debug版本
- 真机-Release版本
- 模拟器-Debug版本
- 模拟器-Release版本
最终生成结果
7.合并 debug 两个包和 release 两个包
注意:这里的合并指的是 1.debug 下真机+模拟器合并 2.release 下真机+模拟器合并
7.1将4个.a文件拷贝到单独文件夹
7.2 合并
打开终端
命令规则
lipo -create+空格+模拟器Debug路径+空格+模拟器Release路径+空格-output+空格+输出路径+输出名字(可自定义)
例如:
lipo -create /Users/fujia/Desktop/framework/StaticFramework-Release-iphoneos /Users/fujia/Desktop/framework/StaticFramework-Release-iphonesimulator -output /Users/fujia/Desktop/framework/StaticFramework-Release
- 1
- 2
- 3
- 4
标注出是自己起名
同理 release 也是如此 最后生成两个文件
**7.3替换文件
7.3.1寻找之前生成的 任意framework
**7.3.2替换二进制文件
替换前
替换后
8.使用方法
8.1新建工程
8.2应用 framework
8.3结果如下
9.注意的地方
9.1警告
如果我们什么都不配置的话 应用 framework 里面的文件 会产生如下的警告
missing submodule ‘StaticFramework.framewokrTool”
解决方案:
在 framework 的头文件也就是创建 framework 时同名的.h里面引入我们的头文件
就可以了
9.2资源文件 .bundle
静态库中有使用到图片、音视频等资源文件,可以将这些文件打包成.bundle文件供静态库使用。
最简单的方法是,新建一个文件夹,将图片、音视频等资源拖到文件夹中,将文件夹后缀名改为.bundle.
静态库想要使用里面的资源的话需要先获取到该.bundle文件。
NSBundle *bundle = [NSBundle bundleWithPath: [[NSBundle mainBundle] pathForResource:@"BundleName" ofType: @"bundle"]];
- 1
静态库中使用.bundle文件里面的图片的方法是:
NSString *imageName = [[bundle resourcePath] stringByAppendingPathComponent:assetName];
[_imageView setImage:[UIImage imageWithContentsOfFile:imageName]];
- 1
- 2
⚠️注意:.bundle文件无法封装到framework里,需要将.framework,.bundle同时导入项目中才能正常使用
9.3使用category
在制作framework的时候,如果使用了category,则使用该framework的项目运行时会crash,此时需要在该工程中 other linker flags添加一个参数 -ObjC
参数说明
ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中
all_load:会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force_load参数。
force_load:所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载