目录
一、库
二、静态库、动态库、Framework
三、打包静态库
1、
.a
静态库和.framework
静态库的区别2、模拟器和真机的CPU架构
3、打包
.a
静态库4、打包
.framework
静态库
一、库
库其实就是一个编译好的二进制文件,我们常见的.a
、.dylib
和.framework
等都是库,是代码保密和代码复用的一种方式,可以分为静态库和动态库。
二、静态库、动态库、Framework
1、静态库
静态库是指在link
阶段就会被链接进可执行文件的库。
静态库的优点就在于它在link
阶段就会被链接进可执行文件,因此可执行文件没有什么外部依赖,可以直接运行,运行时不会产生额外的开销。但是静态库的缺点就是会使可执行文件的体积变大。
那什么情况下我们会用到静态库呢?一种情况就是我们要把代码共享给别人使用,但是又不想让他们看到源码,就可以给他们静态库;另一种情况是我们自己要复用一些不会经常改动的代码,也可以使用静态库,这样可以减少编译时间,因为库是已经编译好了的。
静态库的存在形式有.a
和.framework
,直接打包的静态库后缀名为.a
(akynesis),用Framework打包的静态库后缀名为.framework
。
2、动态库
而动态库则不会在link
阶段被链接进可执行文件,而是在build
可执行文件的时候,我们先指定可执行文件将来需要依赖哪些动态库,然后等可执行文件开始运行的时候,操作系统再把这些动态库一块加载到内存中,供可执行文件运行使用。如果多个可执行文件依赖同一个动态库,那么操作系统就只会加载一份动态库到内存中,然后把它共享给所有相关的可执行文件使用。
动态库的优点就是不影响可执行文件的体积,但是动态库动态加载的特性在运行时会造成一定的性能损耗。
那什么情况下我们会用到动态库呢?其实动态库主要就是用来供多个可执行程序共享的,但是我们知道iOS应用都是运行在沙盒中,不同的程序之间根本不能共享代码,所以咱们自己写动态库根本就不可能用到。也正因为如此,虽然我们能打包动态库,但是苹果明令禁止我们打包动态库,否则上架被拒,还是乖乖地由苹果写动态库,咱们用苹果写的就可以了。
动态库的存在形式有.dylib
和.framework
,直接打包的动态库后缀名为.dylib
(dynamic library),用Framework打包的动态库后缀名为.framework
。
3、Framework
Framework既可以是静态库,也可以是动态库。
三、打包静态库
因为苹果明令禁止我们打包动态库,否则上架被拒,所以接下来我们只演示静态库的打包。
1、.a
静态库和.framework
静态库的区别
其实不管是.a
静态库还是.framework
静态库,我们在供给别人使用的时候,一定是提供(二进制文件)+(.h
文件)+(资源文件)三部分内容的,只不过.a
静态库恰好就是这样一个模式,而.framework
静态库则只有一个库,里面包含了这三部分内容而已。
.a
静态库只会把代码打包进库里,不会把.h
文件、资源文件(如图片、xib等)打包进库里,所以我们打包完.a
静态库之后,会得到.a
静态库、.h
文件和资源文件三部分内容,我们还需要自己创建一个静态库文件夹来把它们打包一下再交付给别人使用。
.framework
静态库会把代码、.h
文件和资源文件一块打包进库里,所以我们打包完.framework
静态库之后,只会得到一个.framework
静态库,只不过你能看到.h
文件,看不到资源文件。
(.a
静态库) + (.h
文件) + (资源文件) = (.framework
静态库)
2、模拟器和真机的CPU架构
静态库在哪种CPU架构下打包,就只支持哪种CPU架构,如果静态库不支持某种CPU架构,那么静态库在该CPU架构下是无法通过编译的。
-
模拟器
4S~5:i386
5S~XS Max:x86_64 -
真机
3GS~4S:armv7
5~5C:armv7s(armv7s和armv7互相兼容,静态库只要支持其中一个,在另一个架构下就能编译通过)
5S~XS Max:arm64
3、打包.a
静态库
- 第一步:创建
.a
静态库工程并编写静态库代码
创建.a静态库工程,取名YYBase

创建后文件目录如下

然后编写静态库代码,比如此处在YYBase
类里声明并实现一个方法用来测试
-----------YYBase.h-----------
#import <Foundation/Foundation.h>
@interface YYBase : NSObject
+ (void)test;
@end
-----------YYBase.m-----------
#import "YYBase.h"
@implementation YYBase
+ (void)test {
NSLog(@"test");
}
@end
- 第二步:配置想暴露给外界的头文件
创建一个Header Phase

创建后如下

点击加号添加想要暴露给外界的头文件

添加后如下

把头文件从Project栏拖到Public栏完成暴露

- 第三步:配置静态库支持所有模拟器和真机的架构

- 第四步:配置静态库为Release版本
因为静态库的主要用途是打包出来给别人或自己用的,那你给别人交付的静态库肯定不需要是Debug版啊,难不成还让别人调试吗,所以我们打包静态库要选Release版本,减少包的体积加快运行速度。
不过我们自己私下里在编写或者修改静态库的时候,可以改为Debug来调试,最后打包的时候要选Release版本。


- 第五步:打包模拟器静态库,供模拟器使用
选中模拟器,cmd+b

.a文件变黑,说明静态库生成成功

选中.a文件,Show in Finder,文件目录如下

- 第六步:打包真机静态库,供真机使用
选中Generic iOS Device或插入真机选中,cmd+b

.a文件变黑,说明静态库生成成功

选中.a文件,Show in Finder,文件目录如下

- 第七步:合并模拟器静态库和真机静态库,模拟器和真机都能使用
需要用终端合并,命令格式为:lipo -create 真机.a文件路径 模拟器.a文件路径 -output 合并后的.a文件路径
。
打开终端,输入下面的指令:
lipo -create /Users/yiyi/Library/Developer/Xcode/DerivedData/YYBase-aktvhdicknregncrbwimaxlucgvc/Build/Products/Release-iphoneos/libYYBase.a /Users/yiyi/Library/Developer/Xcode/DerivedData/YYBase-aktvhdicknregncrbwimaxlucgvc/Build/Products/Release-iphonesimulator/libYYBase.a -output /Users/yiyi/Library/Developer/Xcode/DerivedData/YYBase-aktvhdicknregncrbwimaxlucgvc/Build/Products/libYYBase.a
合并成功后就会发现文件目录里确实多出来一个合并后的.a
文件

此时我们可以在终端通过lipo -info 静态库.a文件的路径
指令来查看下它所支持的架构。
打开终端,输入下面的指令:
lipo -info /Users/yiyi/Library/Developer/Xcode/DerivedData/YYBase-aktvhdicknregncrbwimaxlucgvc/Build/Products/libYYBase.a
命令执行后,我们发现该静态库支持armv7 i386 x86_64 arm64
模拟器和真机的四种架构
Architectures in the fat file: /Users/yiyi/Library/Developer/Xcode/DerivedData/YYBase-aktvhdicknregncrbwimaxlucgvc/Build/Products/libYYBase.a are: armv7 i386 x86_64 arm64
- 第八步:创建一个静态库文件夹打包
.a
静态库和.h
文件共外界使用
这个时候我们需要创建一个静态库文件夹,把合并后的.a
静态库和随便一个user下的include文件拖进我们自己创的文件夹里,然后交给别人使用就可以了。

比如,我们现在有一个Test项目,引入了我们的静态库后,可以正常使用

- 第九步:那我们怎么把图片等资源打包进
.a
静态库呢,以图片为例
比如现在,我们要给libYYBase静态库新增了一个读取图片的功能。
新建一个文件夹后缀名改为.bundle
,名字按自己的需求取,把静态库里用到的图片放进去,拖进静态库工程里,新增后目录如下

然后为静态库新增读取图片的代码
-----------YYBase.h-----------
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface YYBase : NSObject
+ (void)test;
+ (UIImage *)readImage;
@end
-----------YYBase.m-----------
#import "YYBase.h"
@implementation YYBase
+ (void)test {
NSLog(@"test");
}
+ (UIImage *)readImage {
NSString *resourceBundlePath = [[NSBundle mainBundle] pathForResource:@"Resource" ofType:@"bundle"];
NSBundle *resourceBundle = [NSBundle bundleWithPath:resourceBundlePath];
NSString *imagePath = [resourceBundle pathForResource:@"testImage" ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
return image;
}
@end
cmd+b,生成新的静态库,然后把新静态库、.h
文件和资源文件一块放在静态库文件夹内,交付给外界。

比如,现在Test项目就会变成这样

4、打包.framework
静态库
其实和打包.a
静态库基本上一模一样。
第一步:创建一个.framework
工程并编写静态库代码
创建.framework
新工程,取名YYBase

创建后文件目录如下,自带的头文件用来让我们把静态库里所有要公开的头文件都在这里引入

然后编写静态库的代码,比如此处创建一个YYTest
类里声明并实现一个方法用来测试

-----------YYTest.h-----------
#import <Foundation/Foundation.h>
@interface YYTest : NSObject
+ (void)test;
@end
-----------YYTest.m-----------
#import "YYTest.h"
@implementation YYTest
+ (void)test {
NSLog(@"test");
}
@end
- 第二步:配置framework打包静态库
因为framework既可以打包静态库也可以打包动态库,而且默认是打包动态库,所以我们要配置它打包静态库。

-
第三步:配置想暴露给外界的头文件
-
第四步:配置静态库支持所有模拟器和真机的架构

- 第五步:配置静态库为Release版本

- 第六步:打包模拟器静态库,供模拟器使用
选中模拟器,cmd+b

. framework
文件变黑,说明静态库生成成功

选中. framework
文件,Show in Finder,文件目录如下

- 第七步:打包真机静态库,供真机使用
选中Generic iOS Device或插入真机选中,cmd+b

. framework
文件变黑,说明静态库生成成功

选中. framework
文件,Show in Finder,文件目录如下

- 第八步:合并模拟器静态库和真机静态库,模拟器和真机都能使用
需要用终端合并,命令格式为:lipo -create 真机文件路径 模拟器文件路径 -output 真机文件路径
命令还是一样的命令,只不过framework不是直接合并framework,而是其下的文件


打开终端,输入下面的指令
lipo -create /Users/yiyi/Library/Developer/Xcode/DerivedData/YYBase-aktvhdicknregncrbwimaxlucgvc/Build/Products/Release-iphonesimulator/YYBase.framework/YYBase /Users/yiyi/Library/Developer/Xcode/DerivedData/YYBase-aktvhdicknregncrbwimaxlucgvc/Build/Products/Release-iphoneos/YYBase.framework/YYBase -output /Users/yiyi/Library/Developer/Xcode/DerivedData/YYBase-aktvhdicknregncrbwimaxlucgvc/Build/Products/YYBase.framework/YYBase
合并成功后会替换掉真机原来的文件,我们直接用真机的这份framework就行了,它已经兼容真机和模拟器的版本了
此时我们可以在终端通过lipo -info 静态库.a文件的路径来查看下它所支持的架构
lipo -info /Users/yiyi/Library/Developer/Xcode/DerivedData/YYBase-aktvhdicknregncrbwimaxlucgvc/Build/Products/Release-iphoneos/YYBase.framework/YYBase
命令执行后,我们发现该静态库支持armv7 i386 x86_64 arm64模拟器和真机的四种架构
Architectures in the fat file: /Users/yiyi/Library/Developer/Xcode/DerivedData/YYBase-aktvhdicknregncrbwimaxlucgvc/Build/Products/Release-iphoneos/YYBase.framework/YYBase are: i386 armv7 x86_64 arm64
- 第九步:用framework打出来的静态库我们不需要自己创建静态库文件夹,直接把
.framework
静态库供给外界使用就可以了

比如,我们现在有一个Test项目,引入了我们的静态库后,可以正常使用

- 第十步:那我们怎么把图片等资源打包进
.framework
静态库呢,以图片为例
其实和上面.a
的差不多,直接把放好图片的.bundle
文件拖进去,编写新的静态库代码,需要注意读取资源的时候和上面.a
不太一样了,路径需要加上你的framework
+ (UIImage *)readImage {
NSString *resourceBundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"YYBase.framework/Resource.bundle"];
NSBundle *resourceBundle = [NSBundle bundleWithPath:resourceBundlePath];
NSString *imagePath = [resourceBundle pathForResource:@"testImage" ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
return image;
}
cmd+b重新生成一下静态库,然后把新静态库拖进测试项目中,此时需要多一步,要不然资源文件读取不到

参考博客:
库
iOS库 .a与.framework区别
ios打包静态库,看这篇就够了
绝对手把手教你如何将一整个xcode工程打包成静态库
网友评论