iOS - 静态库.a 和 framework 详解

一、基本概念

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 静态库

![041_01](http://os1i62usc.bkt.clouddn.com/041_01.jpg)
![042_02](http://os1i62usc.bkt.clouddn.com/042_02.jpg)

2.配置工程环境

2.1 配置最低支持版本

![041_03](http://os1i62usc.bkt.clouddn.com/041_03.jpg)

2.2 设置适配所有模拟器架构重要

project -> buildSeting -> Build Active Architecture Only 设为NO

![041_04](http://os1i62usc.bkt.clouddn.com/041_04.jpg)

Build Active Architecture Only:指定是否只对当前连接设备所支持的指令集编译 设置为 YES,是为了 Debug 的时候编译速度更快,它只编译当前的 Architecture 版本,而设置为 NO 时,会编译所有的版本。 所以,一般默认 Debug 设置为 YES,Release 时为 NO,以适应不同设备。但是我们是在 Debug 模式下创建所有机型都可执行的静态库,所以我们要把 Bebug 下设置 NO。若为 YES,那么编译出来的.a 静态库就只包含当前设备的指令集。

3.添加自己要封装的文件

头文件最好一起放在一个.h 文件中,方便使用时只导入一个h 文件,这里放在 TestStaticHeader 里;

如果需要用到图片,可以添加 Bundle 文件:

![041_05](http://os1i62usc.bkt.clouddn.com/041_05.gif)

4.修改项目配置,把要暴露的 .h 文件,添加到 Target-> Build Phases -> Copy Files

![041_06](http://os1i62usc.bkt.clouddn.com/041_06.gif)

添加暴露的头文件的另一种方式,是添加 Headers 里的 Public 中:

![041_07](http://os1i62usc.bkt.clouddn.com/041_07.jpg)
![041_08](http://os1i62usc.bkt.clouddn.com/041_08.jpg)

5.生成.a 文件

此处注意需要生成 4 个

5.1修改环境

![041_09](http://os1i62usc.bkt.clouddn.com/041_09.jpg)
![041_10](http://os1i62usc.bkt.clouddn.com/041_10.jpg)

5.2 选择模拟器+Debug 环境+“cmd+R”生成.a

![041_11](http://os1i62usc.bkt.clouddn.com/041_11.jpg)

此处注意需要生成4个 如此类推打出四种.a

  • 真机-Debug版本
  • 真机-Release版本
  • 模拟器-Debug版本
  • 模拟器-Release版本

最终生成结果:

![041_12](http://os1i62usc.bkt.clouddn.com/041_12.jpg)

5.3 合并 debug 两个包和 release 两个包

注意:这里的合并指的是 1.debug 下真机+模拟器合并 2.release 下真机+模拟器合并

(1)将4个.a文件拷贝到单独文件夹

![041_13](http://os1i62usc.bkt.clouddn.com/041_13.jpg)

(2)合并

打开终端,切到上述文件夹目录,执行以下语句

lipo -create+空格+模拟器Debug路径+空格+模拟器Release路径+空格-output+空格+输出路径+输出名字(可自定义)
复制代码
![041_14](http://os1i62usc.bkt.clouddn.com/041_14.jpg)

同理 release 也是如此,最后生成两个文件

![041_15](http://os1i62usc.bkt.clouddn.com/041_15.jpg)

好了,这样就创建完.a 静态库了,使用的时候,只需在工程中导入.a 文件和暴露的.h 文件,配置 Header search path 路径就可以了。

注意:如果静态库中有 category 类,则在使用静态库的项目配置中【Other Linker Flags】需要添加参数【-ObjC]或者【-all_load】。 为了开发方便,我们可以使用生成的通用静态库,但是最终上线的使用我们可以只导入真机的,这样工程的体积也会小一些。

三、制作 framework 静态库

1.新建 framework 工程

![041_16](http://os1i62usc.bkt.clouddn.com/041_16.jpg)

2.新建文件类

![041_17](http://os1i62usc.bkt.clouddn.com/041_17.jpg)

3.修改工程文件配置

build setting ->搜索 mach -> 修改 mach -O Type ->static Library

![041_18](http://os1i62usc.bkt.clouddn.com/041_18.jpg)
![041_19](http://os1i62usc.bkt.clouddn.com/041_19.jpg)

⚠️注意:如果需要导入第三方静态库,在拖入工程添加的时候,不要勾选添加到target中。

4.暴露头文件

![041_20](http://os1i62usc.bkt.clouddn.com/041_20.jpg)

5.生成 .framework

5.1 修改环境

![041_21](http://os1i62usc.bkt.clouddn.com/041_21.jpg)

这里可以选择 Debug 和 Release 环境

![041_22](http://os1i62usc.bkt.clouddn.com/041_22.jpg)

5.2 选择模拟器+Debug 环境+“cmd+R”生成.a

![041_23](http://os1i62usc.bkt.clouddn.com/041_23.jpg)

此处注意需要生成4个 如此类推打出四种.framework

  • 真机-Debug版本
  • 真机-Release版本
  • 模拟器-Debug版本
  • 模拟器-Release版本

最终生成结果

![041_24](http://os1i62usc.bkt.clouddn.com/041_24.jpg)

6.合并 debug 两个包和 release 两个包

注意:这里的合并指的是 1.debug 下真机+模拟器合并 2.release 下真机+模拟器合并

6.1 将 4 个 .framework 文件拷贝到单独文件夹

![041_25](http://os1i62usc.bkt.clouddn.com/041_25.jpg)

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 也是如此,最后生成两个文件。

![041_26](http://os1i62usc.bkt.clouddn.com/041_26.jpg)

6.3替换文件

(1)寻找之前生成的 任意framework (2)替换二进制文件

替换前:

![041_27](http://os1i62usc.bkt.clouddn.com/041_27.jpg)

替换后:

![041_28](http://os1i62usc.bkt.clouddn.com/041_28.jpg)

大功告成。

原文链接:iOS - 静态库.a 和 framework 详解

转载于:https://juejin.im/post/5b9f6a46e51d450e4006aa5c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值