App打包-001-静态库(.a和.framework)和动态库的区别与制作,以及使用

 

 引言

在开发中.framework静态库还是比较常见的,我们可以把一些不愿意让别人见到的代码,用静态库的方式把它隐藏起来,只留下.h文件显示方法供编程人员使用。而.a文件出了静态库本身外,还需要引入.h文件,而.framework就不需要如此,由于.framework的方便性所以一般情况下我们见到的较多。

库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。 
静态库:以.a.framework为文件后缀名。
动态库:以.tbd(之前叫.dylib) 和 .framework 为文件后缀名。

静态库可以做什么:

1.定义基础的数据类

2.定义视图类

3.定义视图控制器类

静态库与动态库的区别

静态库和动态库是相对编译期和运行期的:

动态库:运行时获取

静态库:只读一次,编译时获取

//注意:苹果禁止一切未开源的代码在APP中使用,也就是说上传APP的时候,要将代码告知给苹果,审核通过之后才能上传使用,若苹果发现上传的APP中包含静态库或者动态库则会拒绝上架。

001-静态库.a 创建

1.新建工程

比如我们的工程名叫HKLibTest,那么我们创建的.a 静态库最好就是前面加个Lib,如:LibHKLibTest.a

新建工程 (选中xcode,按commond + shift + N) 

此时工程目录是这个样子,.a文件还没有被创建,因此是红色的 

 

你可以把图中 HKLibTest.h.m 换成你自己要生成库的文件(可以是多个),在这里我就不换了,就用这两个文件,我们在.h文件中添加一个方法+sayHello,并在.m中实现它

#import "HKLibTest.h"

@implementation HKLibTest
+ (void)sayHello {
    NSLog(@".a静态库:Hello, World ~");
}
@end

2.添加Headers

按照下图顺序进行操作 

Build Phases ->添加 -> New Run Script Phase 

 

 

 选中所有的.h文件,在点击Add

/*
这里需要注意的是暴露出来的头文件中import的其他类也得添加到public中暴露出来。 
如果不想将import的类暴露出来,那么在头文件中用@class 然后在对应的.m文件中再import。 
总之 
1. 你再外面用到的类,一定要暴露出来; 
2. 你暴露出来的类,头文件中导入的类也一定是暴露出来的 
3. 如果提示导入头文件报错,找不到文件,找不到谁暴露谁就对了
*/

3. 进行打包前的一些配置

设置编译模式,打开xcode菜单Product -> Scheme -> Edit Scheme,改成release模式,如下图 

 

 

 

编译机器的选择,如下图,一定要选择NO。(如果选择yes,生成部分机型,选择NO则适配所有机型)

4. 接下来,我们进行打包

 操作简述: Command + B
1. 在真机情况下编译Generic iOS Device),并记录下.a文件的绝对路径 
2. 在模拟机情况下编译(随便吧,我用的是iPhone8Plus),并记录下.a文件绝对路径 
3. 用命令行合并1、2部记录的文件,到新的.a文件,名字最好取开始我们取的名字吧,命令行:lipo -create 真机静态库路径空格模拟器静态库路径 -output 最终文件路径(桌面)
4. 把你要暴露的.h文件和你已经生成的.a文件搞到一个文件夹里,这个文件夹就可以直接拖到工程里用啦

//真机静态库路径
/Users/MengYu/Library/Developer/Xcode/DerivedData/HKLibTest-cqiexexehimllgdmfaxigfagpzet/Build/Products/Release-iphoneos/libHKLibTest.a
//模拟器静态库路径
/Users/MengYu/Library/Developer/Xcode/DerivedData/HKLibTest-cqiexexehimllgdmfaxigfagpzet/Build/Products/Release-iphonesimulator/libHKLibTest.a

合成:

//$lipo -create /Users/MengYu/Desktop/真机静态库/libHKLibTest.a  /Users/MengYu/Desktop/模拟器静态库/libHKLibTest.a -output /Users/MengYu/Desktop/LibHKLibTest.a

在桌面就可以看到合成之后的.a文件了

把我们刚合成的.a文件和想暴露的.h文件,弄到一个文件夹下

静态库创建完成~

导入HKDemo工程中:

#import "ViewController.h"
#import "HKLibTest.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [HKLibTest sayHello];
}

补充:

查看.a文件/.Framework是否正确lipo -info

$lipo -info 真机模式下的.a文件路径 

/Users/MengYu/Desktop/真机静态库/libHKLibTest.a is architecture: arm64真机

//真机 armv7 arm64 
$lipo -info 模拟器下的.a文件路径

/Users/MengYu/Desktop/模拟器静态库/libHKLibTest.a is architecture: x86_64模拟器

//模拟器 i386 x86_64

.FrameWork :

模拟器

//$lipo -info /Users/MengYu/Desktop/HKFrameWork.framework/HKFrameWork 
Architectures in the fat file: /Users/MengYu/Desktop/HKFrameWork.framework/HKFrameWork are: i386 x86_64

真机

//$lipo -info /Users/MengYu/Desktop/HKFrameWork.framework/HKFrameWork 
Architectures in the fat file: /Users/MengYu/Desktop/HKFrameWork.framework/HKFrameWork are: armv7 armv7s i386 x86_64 arm64 

  

/*
1.category是我们实际开发项目中经常用到的,把category打成静态库是没有问题的,但是在用这个静态库的工程中,调用category中的方法时会有找不到该方法的运行时错误(selector not recognized),解决办法是:在使用静态库的工程中配置other linker flags的值为-ObjC。
2.如果一个静态库很复杂,需要暴露的.h比较多的话,就可以在静态库的内部创建一个.h文件(一般这个.h文件的名字和静态库的名字相同),然后把所有需要暴露出来的.h文件都集中放在这个.h文件中,而那些原本需要暴露的.h都不需要再暴露了,只需要把.h暴露出来就可以了。
*/

002-静态库.Framework创建

1.新建工程

 这里我使用的是Xcode9,选择Cocoa Touch Framework,然后点next。

 2、创建功能类或者拖入已有的功能类,并实现功能类的功能

3、更改Xcode项目配置

 1> Architectures 修改 BuildingSettings 添加 armv7s 

  Build Active Architecture Only 设置为NO

  

 2> Mach-O Type  设置为 Static Library 

  

 3> 添加Headers 同.a 静态库 (Build Phrases)

 

 4>然后需要在HKFrameworkTest.h(必须是公开的,否则无法引用)中将你所有要公开的.h引入

 

4、开始打包Framework

 1>选择真机,点击Generic iOS Device Command + B 编译 ,获取真机Framework路径;

 2>选择模拟器,点击iPhone8Plus Command + B 编译 ,获取模拟器Framework路径;

 3>合成Framwork

lipo -create 真机版本路径 模拟器版本路径 -output 合并后的文件路径/名称

1.合并操作很容易出现问题,当提示这个错误时:

//error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: can't move temporary file: /Users/xiong/Desktop/demo to file: /Users/xiong/Desktop/demo.lipo (Is a directory)

解决方法:
此错误一般是在合并后的路径没有加上合并后生成的文件名字,加上就行。

2.正确:

lipo -create /Users/MengYu/Library/Developer/Xcode/DerivedData/HKFrameWork-hfsogjyrorjfqchkyodzhhgyfwgs/Build/Products/Release-iphoneos/HKFrameWork.framework/HKFrameWork  /Users/MengYu/Library/Developer/Xcode/DerivedData/HKFrameWork-hfsogjyrorjfqchkyodzhhgyfwgs/Build/Products/Release-iphonesimulator/HKFrameWork.framework/HKFrameWork  -output /Users/MengYu/Library/Developer/Xcode/DerivedData/HKFrameWork-hfsogjyrorjfqchkyodzhhgyfwgs/Build/Products/HKFrameWork

如图所示:

5、将此Framework导入HKDemo工程中

Command +B 编译一下,即可使用我们定义好的 kSCREENWIDTH

终端版:

 //补充

/*
lipo -info [文件名称] :显示静态库文件的架构类型
iphone用lipo合并模拟器库和真机库,发布一个通用的静态库
lipo -create [文件名称1,文件名称2,.......,文件名称n] -output [生成的文件名称] 
//静态库中是不能包含资源文件的!!!(图片,xib,音频等)
需要资源文件的时候,生成file.bundle。
*/

 

一、什么是库?
库是共享程序代码的方式,一般分为静态库和动态库。

二、静态库与动态库的区别?

静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。
动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。

三、iOS里静态库形式?
.a和.framework
四、iOS里动态库形式?
.dylib和.framework

五、framework为什么既是静态库又是动态库?
系统的.framework是动态库,我们自己建立的.framework是静态库。
六、a与.framework有什么区别?
.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。
.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。
.a + .h + sourceFile = .framework。
建议用.framework.

七、为什么要使用静态库?
方便共享代码,便于合理使用。
实现iOS程序的模块化。可以把固定的业务模块化成静态库。
和别人分享你的代码库,但不想让别人看到你代码的实现。
开发第三方sdk的需要。

八、制作静态库时的几点注意:
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暴露出来就可以了。

 常见问题:

1.iOS导入动态库提示Reason:image not found

https://www.jianshu.com/p/bed94ddacfa8

 2.ios自定义Framework 报错 Could not build module

https://blog.csdn.net/fushi007/article/details/79420675

 

posted @ 2018-07-03 14:49  淡然微笑_Steven  阅读(950)  评论(0编辑  收藏  举报