前言
- 我的第一次,请多多指教!目的是给予有需要的朋友以及方便自己日后的查阅。
iOS开发库文件的分类
静态库:
- 静态库有 .a 和 .framework 两种形式;
- 在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库。
动态库:
- .dylib 和 .framework 形式,后来.dylib动态库又被苹果替换成.tbd的形式;
- 在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。
结论
- 同一个静态库在不同程序中使用时,每一个程序中都得导入一次,打包时也被打包进去,形成一个程序;
- 而动态库在不同程序中,打包时并没有被打包进去,只在程序运行使用时,才链接载入(如系统的框架如 UIKit、Foundation 等),所以程序体积会小很多,但是苹果不让使用自己的动态库,否则审核就无法通过(为什么不让使用本人不是很清楚,还请大神普及)。
framework 制作过程
1. 首先新建一个项目,选择 Cocoa touch Framework :
2. 然后随便取一个名字 MyFramework_Create:
3. 然后根据不能的业务需求写好自己的代码,这里因为是测试,我随便写点,新建一个 Dog 类,然后公开一个方法并随便 log 一点东西:
4. 工程配置:
-
4.1 选择工程文件 > target 第一项 > Build Setting > 搜索 linking,然后几个需要设置的选项都显现出来,首先是 Dead Code Stripping 设置为 NO,网上对此项的解释如下,意思是如果开启此项就会对代码中的 " dead ”、" unreachable ” 的代码过滤,不过这个开关是否关闭,似乎没有多大影响,不过为了完整还原 framework 中的代码,将此项关闭也未曾不可。
- The resulting executable will not include any “dead” or unreachable code.
4.2 然后将Link With Standard Libraries关闭,我想可能是为了避免重复链接:
-
4.3 最后将 Mach-O Type 设为 Static Library,framework 可以是动态库也可以是静态库,对于系统的framework 是动态库,而用户制作的 framework 只能是静态库.
5. 头文件的设置:将需要公开的头文件从 Project 中拖入 Public,至于是否需要将私有的头文件拖入Private,我觉得直接放在 Project 中即可,若是 Private 中有头文件,打包以后的 framework 中会多出一个Private 的文件夹包含着放入 Private 的头文件,不过我觉得如果是私有最好还是不要让别人看到。以下有三种设置方法,设置前需要在 .h 文件导入:
-
5.1 在 target 下找到 Build Phases, 点开 Headers 看到 Project 下面的文件直接右键就可以看到一些选项,选择你所需 Public 的即可。
-
5.2 在上面的 Headers 界面的时候直接将 Project 下面的文件拖到 Public 下面即可。
-
5.3 选中 Dog.h 文件,在 Xcode 右边找到 Target Memership 右下角的(注意不是 Xcode 整个界面右下角)上下箭头,那里就有你想要的:
6. iPhone 5 和 iPhone 5c 特殊机型架构的支持配置
-
选中 Build Settings > Architectures > 单击该选项的右边 > other > armv7s ,即可
7. 编译生成 .framework 文件
- 7.1 先选择Generic iOS Device,按下 Command+B:Build 一下:
- 7.2 然后随意选择一个模拟器再次 Build 一下:
8. 合并真机与模拟器生成 .framework 文件:
- 8.1 Show in Finder 找到 Build 后的 framework
- 8.2 我们看到总共有两个文件夹,上面是真机编译生成的文件,下面是模拟器编译生成的文件。
- 8.3 我们在 Products 同级目录下(路径可以任意选)新建一个 名为 MyFramework_Create 的文件夹作为输出路径,这里取名要与项目名一致,至于为什么到后面自己会明白的。
-
8.4 使用命令行合并:lipo -create + 上面两个文件的路径(是指真机与模拟器MyFramework_Create.framework 目录下的 MyFramework_Create文件) + -output + 合成后文件的输出路径。 最后回车即可。
-
8.5 将生成的 MyFramework_Test.lipo 文件删除后缀名并代替真机下的 MyFramework_Test 文件就完成了。
framework的测试
1. 新建名为 MyFramework_Test 的工程,注意选择的是 Single View Application :
![](file:////Users/dinpay/Desktop/MyFramework_Create/新建SingleViewApplication.png)
![](file:////Users/dinpay/Desktop/MyFramework_Create/新建MyFramework_Test.png)
2. 将所需要的头文件导入工程,新建一个 dog 对象,并调用 doSmothing 方法,查看控制台的输出,现在已经成功导入测试完成:
经典报错
1. 缺少相关头文件的路径,在有些博客上看到说在测试之前就要导入 framework 的 Headers 的路径,发现这不完全正确,在我的经验中如果 framework 中引入了第三方不导入会报错,没有引用的就没有报错,所以个人认为还是看情况,如果运行起来报错说找不到头文件的话,那再做相关配置也无妨,配置方法如下:
![](file:////Users/dinpay/Desktop/MyFramework_Create/头文件配置.png)
2. 缺少相关设备架构,报错如下:
- 2.1 库中缺少了i386架构的文件,这时我就比较困惑了,明明将模拟器生成的库文件合并进来了,怎么在模拟器上编不通呢!用 lipo -info 命令查看一下,果然没有i386架构的文件
![](file:////Users/dinpay/Desktop/MyFramework_Create/架构前.png)
-
2.2 重新选择 iPhone 5 模拟器与 iPhone 7 模拟器两者运行生成的 .framework 文件合并后与真机生成的 .framework 文件再次合并查看信息,果然有了
-
2.3 架构总结:
- 对于模拟器来说 4s 和5的模架构是 i386 的32位架构,5s 至今是 x86_64 的64位架构。对于真机来说 3GS~4s 是 armv7 架构,5 和 5c 是 armv7s 架构,5s 至今是 arm64 架构。
3. 将下图中的选项设为 YES,导致其编译时只生成当前机器的框架,将其设置为 NO 后,发现用模拟器编译后生成的 framework 同时包含 x86_64 和 i386 架构。
4. 在项目中引入静态库后,archive 的时候会出现错误
-
解决办法:
- Bitcode 是苹果在 Xcode7 及以后推出的新功能。用于代码的二次编译,针对 CPU 进行优化,编译工作由苹果 AppStore 后台来完成。针对 iOS 是可选项,默认打开。watchOS 和 tvOS 是必选项,所以需要打开库工程的此选项并加上 -fembed-bitcode 参数,重新编译。