Framework 制作

Framework 制作

前言


可以看出.a的封装和.framework的封装差不多,也有模器和真机合并的程,通片我可以看出.a .framework的区,就是.a+.h+soureFile=.framework。可以看出我直接封装.framework是最好的。那么我就来看看framework怎么封装的。


实现步骤:

一、新建 Project - Framework&Library - Cocoa TouchFramework,点击Next,然后选择语言和输入项目库名称


立完成,会看到默生成的一个 xxx.h  Info.plist  文件(只看框内)

解释一下这两个文件:

xxx.h 文件的作用是整个包对外提供的入口头文件,除了正常定义参数属性之外,还有

1、提供Swift项目内引用的OC文件的import引用,注意,这里引用之前必须在Build Phrases的Headers内暴露到 Public

2、提供所有对外访问文件(包括第三方文件)的import引用

info.plist文件的作用就如同正常项目的plist文件作用,用来定义或添加一些属性。

 

二、添加文件,这里可以自己新建,或者从已有项目拷贝过来都可以

1、这里要注意一下:由于打包类库工程不是一个完整项目工程,所以并没有AppDelegate等文件,所以涉及到这些的文件要额外处理,或改代码,或适当改变功能。

2、注意:工程如果有桥接文件,是不能拷贝过来的,否则编译不通过。因为正常情况下,如果我们swift项目引入了oc文件,我们必须通过一个桥接文件来处理两者之间的转换,而我们在新建类库包的时候,是禁止桥接文件存在的,即使你添加了,也会永远编译不过,打包不了。

所以这里就用到这个 xxx.h 头文件了。我们可以通过这个文件来实现两者之间的转换,前提就是必须先将oc的.h暴露出来,否则即使你import,也会报错找不到.h 文件。

3、PS:这里涉及到一个资源文件的问题,比如图片、视频、音频以及xib、storyboard等的处理。之前正常项目的做法可能是这样:

1:直接用Assets.xcassets

2:新建resources文件夹,存放图片

但这里,需要注意一点:

对于方法1,这样做是无效的,我们可以新建一个bundle文件,将图片移植过来。

对于方法2,我们可以在本地,直接修改添加后缀.bundle实现

然后另一个重点就是路径问题:

由于类库的资源文件,当我们在正式项目使用时,查找的路径文件不是针对项目,而是针对类库的路径,所以我们这里引用的资源文件路径都要改变一下,而且类库里的其他xib、storyboard文件引用路径都需要更改一下。

修改办法有两种,注意其后续的资源bundle导入到主程序中的方式也会不同。以图片为例:

第一种:NSBundle传不传无所谓

NSBundle *bundle = [NSBundle bundleForClass:[selfclass]];

UIImage *image = [UIImage imageNamed:@"xxx.bundle/片名" inBundle:bundlecompatibleWithTraitCollection:nil];

 

第二种:[UIImage imageNamed:[NSStringstringWithFormat:@" xxx.framework/xx.bundle/%@",name]];

4、.framework三方库打入到自己的库中

其实framework就是在.a静态库基础上的更上一层封装,包含了资源,二进制文件和头文件,并生成统一格式方便用户调用有点类似<.dylib和.tbd>,并不是重新生成的另外一种形式,只是对老的格式进行了一层更规范的封装,统一管理资源文件、头文件和库的二进制文件。所以如果你需要的.a文件其实就在.framework文件中,以友盟为例:手动把二进制文件改成.a的后缀,带上头文件,然后调用他吧...

1)首先找到友盟的二进制文件(注意:别找快捷方式的)

2)将找到的二进制文件UMMobClick改成.a后缀,并将其拖动到Headers文件夹下去,并将Headers文件夹改名为UMMobClick,如此已将.framework改为了.a,后续集成步骤参考下面“.a三方库打入到自己的库中

5、.a三方库打入到自己的库中

1).a、头文件以及.bundle添加到自己的库中,注意勾选Coby…Add to target选项,完成后结果如图

.a库文件,项目中和Build Phases都存在


.h头文件,目中和Build Phases都存在


.bundle资源文件,目中和Build Phases都存在


2)配置.a库的系统依赖库


注意:添加所需要依赖的系统库,这里需要添加的.dylib如果使用新的.tbd编译会报错,简单的处理就是还替换添加.dylib的库<在Link BinarywithLibaraies中点击加号->AddOther...->Shift + Command + G组合键->输入/usr/lib->找到需要添加的库,具体步骤如下:

(1)可以通过加入的.tbd找到对应.dylib的存储路径,如图:


(2)根据路径找到对应的.dylib

点击Build Phases -> Link Binary With Libraries ->加号


然后点击Add Other…


按下“command+shift+g”进入文件夹输入方式,将第一步中的路径拷贝进入


(3)将找到的.dylib加入进来,并将对应的.tbd删除


3)设置.a库和头文件的访问路径

 

三、参数配置

1、选择工程文件>target第一项>Build Setting>搜索linking,然后几个需要设置的选项都显现出来,首先将Mach-O Type设为Static Library,framework可以是动态库也可以是静态库,对于系统的framework是动态库,而用户制作的framework只能是静态库。


2、然后将LinkWith Standard Libraries关闭,我想可能是为了避免重复链接

3、将DeadCode Stripping设置为NO,网上对此项的解释如下,大致意思是如果开启此项就会对代码中的”dead”、”unreachable”的代码过滤,不过这个开关是否关闭,似乎没有多大影响,不过为了完整还原framework中的代码,将此项关闭也未曾不可。

4、增加支持armv7s,在Architectures下增加armv7s,并选中。将Build Active Architecture Only 设置为NO。

5、Enable Bitcode设置为NO;(支持旧库)

6、设置Headers,你要公开的头文件拖至Public下,要隐藏的放在Private或者Project下,当然,隐藏的头文件就无法再被引用。注意:如果公开的类中导入了非公开的类,则外部导入库文件后会报错,找不到对应的文件,需要将公开类中导入的类都公开

7、设置是否将三方.a库文件打包进自定义库中(可以解决库冲突)。如果打包进入,则需要在自定义库项目中和Build Phases -> Link Binary With Libraries中都加入该.a库文件,如图:

如果不打包进入,则将Build Phases -> Link Binary With Libraries中都的该.a库文件删除,项目中存在就行。如图:

 

四、一切准备好后,打包静态库

1、需要分别选择真机和模拟器进行编译

真机

模拟器


编译成功后都会在Products文件夹下生产对应的.framework库文件


2、合并真机和模拟器库

选中上图中Products文件夹下的.framework,然后右键show in finder。


上图一个是Debug-iphoneos(真机)下的,一个是Debug-iphonesimulator(模拟器)下的。通过终端命令行进行合并,命令(lipo -create iphoneosframeworkTest的路径 simulatorframeworkTest的路径 -output 路径,如图:

如此会在目标路径生成一个.lipo后缀的文件


3、将上面的.lipo文件改为你的库文件名(比如我的是JCOpenKit)


并且去掉后缀,然后替换到Debug-iphoneos(真机)或Debug-iphonesimulator(模拟器)路径下对应的文件,如下图


最后将被替换文件的JCOpenKit.framework就是最终的库 


五、引用自定义的framework

1、将.framework库添加到项目中,需要copy,以及勾选Add totargets

结果如图:


2、至于资源文件夹bundle的导入有两个方式。注意:下面的两种导入方式是根据在制作库文件时,资源文件的访问方式不同决定的

第一种,直接将bundle单独导入到项目中,也需要copy,以及勾选Add totarget,如图:


其在库文件中资源访问方式为(以图片为例):NSBundle传不传无所谓

NSBundle*bundle = [NSBundle bundleForClass:[self class]];

UIImage*image = [UIImage imageNamed:@"xxx.bundle/片名"inBundle:bundle compatibleWithTraitCollection:nil];

第二种,无需将bundle单独导入项目中,而是将.framework文件作为资源文件添加到BuildPhases -> Copy Bundle Resources下


其在库文件中资源访问方式为(以图片为例):

[UIImageimageNamed:[NSString stringWithFormat:@" xxx.framework/xx.bundle/%@",name]];

3、导入依赖库,包括自定义库以及自定义库中引入的三方库的依赖库都得导入

4、配置参数:

1)设置.framework库的访问路径

2)如果.framework库中用到了Category类别,则需要在OtherLinker Flags中添加-ObjC

下面讲下Other Linker Flags中参数的作用:

C代码到可执行文件经历的步骤是:源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件

在最后一步需要把.o文件和C语言运行库链接起来,这时候需要用到ld命令。源文件经过一系列处理以后,会生成对应的.obj文件,然后一个项目必然会有许多.obj文件,并且这些文件之间会有各种各样的联系,例如函数调用。链接器做的事就是把这些目标文件和所用的一些库链接在一起形成一个完整的可执行文件。Otherlinker flags设置的值实际上就是ld命令执行时后面所加的参数

下面逐个介绍3个常用参数:

ObjC加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中

all_load会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到ld:duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force_load参数。

-force_load所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载

3)Info.plist设置

如果自定义库中有http的请求,则需要在主程序的Info.plist中加入以下设置,不然会请求失败


5、导入头文件进行接口调用,导入方式

 

参考文档地址:

1、iOS 完整项目制作Framework:https://www.jianshu.com/p/7452db9e37bd

2、iOS封装功能生产.framework:https://www.cnblogs.com/oc-bowen/p/7478461.html

3、iOS 中 Framework 静态库的创建和使用遇到的那些坑:https://blog.csdn.net/qq_31810357/article/details/72528470

4、Xcode 制作iOS静态库SDK<包含第三方.a或者.framework静态库>:https://www.jianshu.com/p/e588bb0411d8

5、iOS xxxx is not an object file(not allowed in a library):https://blog.csdn.net/nine_yao/article/details/72845098

6、iOS 8 Framework 使用加载xib 及图片:https://www.jianshu.com/p/558b44c0fb74

7、Framework 和cocoapod 加载图片问题:https://blog.csdn.net/average17/article/details/79227030

阅读更多
文章标签: Framework 静态库 .a
个人分类: iOS 小记
上一篇NavigationBar 背景色设置
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭