一、基本概念
1.什么是库?
库是共享程序代码的方式,一般分为静态库和动态库。
2.静态库与动态库的区别?
(1)静态库:之所以叫做静态,是因为静态库在编译的时候会被直接拷贝一份,复制到目标程序里,这段代码在目标程序里就不会再改变了。
静态库的好处很明显,编译完成之后,库文件实际上就没有作用了。目标程序没有外部依赖,直接就可以运行。当然其缺点也很明显,就是会使用目标程序的体积增大。被多次使用就有多份冗余拷贝。
(2)动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。
动态库的优点是,不需要拷贝到目标程序中,不会影响目标程序的体积,而且同一份库可以被多个程序使用(因为这个原因,动态库也被称作共享库)。同时,编译时才载入的特性,也可以让我们随时对库进行替换,而不需要重新编译代码。动态库带来的问题主要是,动态载入会带来一部分性能损失,使用动态库也会使得程序依赖于外部环境。如果环境缺少动态库或者库的版本不正确,就会导致程序无法运行(Linux 下常见 lib not found 错误)。
在 iOS8 之后,苹果开始支持开发自己的 framework
。
此时自己构建的 framework
和系统的 framework
还是有区别的,系统的 framework 并不需要复制到目标程序。 自己开发的 framework
无论是动态还是静态的,都要复制到目标程序,所以苹果又把这个叫做 embeded framework
。
3.iOS 里静态库形式?
.a
和.framework
4.iOS 里动态库形式?
.dylib
和.framework
5.framework 为什么既是静态库又是动态库?
系统的.framework
是动态库,我们自己建立的.framework
是静态库。
6.a与.framework 有什么区别?
.a
是一个纯二进制文件,.framework
中除了有二进制文件之外还有资源文件。
.a
文件不能直接使用,至少要有.h
文件配合,.framework
文件可以直接使用。
.a
+ .h
+ sourceFile
= .framework
。
建议用.framework
。
7.为什么要使用静态库?
方便共享代码,便于合理使用。
实现 iOS 程序的模块化。可以把固定的业务模块化成静态库。
和别人分享你的代码库,但不想让别人看到你代码的实现。
开发第三方 sdk
的需要。
8.制作静态库时的几点注意:
1 注意理解:无论是.a
静态库还.framework
静态库,我们需要的都是二进制文件+.h
+其它资源文件的形式,不同的是,.a
本身就是二进制文件,需要我们自己配上.h
和其它文件才能使用,而.framework
本身已经包含了.h
和其它文件,可以直接使用。
2 图片资源的处理:两种静态库,一般都是把图片文件单独的放在一个.bundle
文件中,一般.bundle
的名字和.a
或.framework
的名字相同。.bundle
文件很好弄,新建一个文件夹,把它改名为.bundle
就可以了,右键,显示包内容可以向其中添加图片资源。
3 category
是我们实际开发项目中经常用到的,把 category
打成静态库是没有问题的,但是在用这个静态库的工程中,调用 category
中的方法时会有找不到该方法的运行时错误(selector not recognized),解决办法是:在使用静态库的工程中配置 other linker flags
的值为-ObjC
。
4 如果一个静态库很复杂,需要暴露的.h
比较多的话,就可以在静态库的内部创建一个.h
文件(一般这个.h
文件的名字和静态库的名字相同),然后把所有需要暴露出来的.h 文件都集中放在这个.h 文件中,而那些原本需要暴露的.h
都不需要再暴露了,只需要把.h
暴露出来就可以了。
二、制作.a 静态库
1.新建工程,选择 Cocoa Touch Static Library,创建.a 静态库
2.配置工程环境
2.1 配置最低支持版本
2.2 设置适配所有模拟器架构重要
project -> buildSeting -> Build Active Architecture Only 设为NO
Build Active Architecture Only:指定是否只对当前连接设备所支持的指令集编译 设置为 YES,是为了 Debug 的时候编译速度更快,它只编译当前的 Architecture 版本,而设置为 NO 时,会编译所有的版本。 所以,一般默认 Debug 设置为 YES,Release 时为 NO,以适应不同设备。但是我们是在 Debug 模式下创建所有机型都可执行的静态库,所以我们要把 Bebug 下设置 NO。若为 YES,那么编译出来的.a 静态库就只包含当前设备的指令集。
3.添加自己要封装的文件
头文件最好一起放在一个.h 文件中,方便使用时只导入一个h 文件,这里放在 TestStaticHeader 里;
如果需要用到图片,可以添加 Bundle 文件:
4.修改项目配置,把要暴露的 .h 文件,添加到 Target-> Build Phases -> Copy Files
添加暴露的头文件的另一种方式,是添加 Headers 里的 Public 中:
5.生成.a 文件
此处注意需要生成 4 个
5.1修改环境
5.2 选择模拟器+Debug 环境+“cmd+R”生成.a
此处注意需要生成4个 如此类推打出四种.a
- 真机-Debug版本
- 真机-Release版本
- 模拟器-Debug版本
- 模拟器-Release版本
最终生成结果:
5.3 合并 debug 两个包和 release 两个包
注意:这里的合并指的是 1.debug 下真机+模拟器合并 2.release 下真机+模拟器合并
(1)将4个.a文件拷贝到单独文件夹
(2)合并
打开终端,切到上述文件夹目录,执行以下语句
lipo -create+空格+模拟器Debug路径+空格+模拟器Release路径+空格-output+空格+输出路径+输出名字(可自定义)
复制代码
同理 release 也是如此,最后生成两个文件
好了,这样就创建完.a 静态库了,使用的时候,只需在工程中导入.a 文件和暴露的.h 文件,配置 Header search path 路径就可以了。
注意:如果静态库中有 category 类,则在使用静态库的项目配置中【Other Linker Flags】需要添加参数【-ObjC]或者【-all_load】。 为了开发方便,我们可以使用生成的通用静态库,但是最终上线的使用我们可以只导入真机的,这样工程的体积也会小一些。
三、制作 framework 静态库
1.新建 framework 工程
2.新建文件类
3.修改工程文件配置
build setting ->搜索 mach -> 修改 mach -O Type ->static Library
⚠️注意:如果需要导入第三方静态库,在拖入工程添加的时候,不要勾选添加到target中。
4.暴露头文件
5.生成 .framework
5.1 修改环境
这里可以选择 Debug 和 Release 环境
5.2 选择模拟器+Debug 环境+“cmd+R”生成.a
此处注意需要生成4个 如此类推打出四种.framework
- 真机-Debug版本
- 真机-Release版本
- 模拟器-Debug版本
- 模拟器-Release版本
最终生成结果
6.合并 debug 两个包和 release 两个包
注意:这里的合并指的是 1.debug 下真机+模拟器合并 2.release 下真机+模拟器合并
6.1 将 4 个 .framework 文件拷贝到单独文件夹
6.2 合并
打开终端,输入命令规则
lipo -create+空格+模拟器Debug路径+空格+模拟器Release路径+空格-output+空格+输出路径+输出名字(可自定义)
//For example:
lipo -create /Users/Kaaaaai/Desktop/frameworkProduct/TestStatic_framework-Debug-iphoneos /Users/Kaaaaai/Desktop/frameworkProduct/TestStatic_framework-Debug-iphonesimulator -output /Users/Kaaaaai/Desktop/frameworkProduct/TestStatic_framework-Debug
复制代码
同理 release 也是如此,最后生成两个文件。
6.3替换文件
(1)寻找之前生成的 任意framework (2)替换二进制文件
替换前:
替换后:
大功告成。