前言
如果你想将你开发的控件与别人分享,一种方法是直接提供源代码文件。然而,这种方法并不是很优雅。它会暴露所有的实现细节,而这些实现你可能并不想开源出来。此外,开发者也可能并不想看到你的所有代码,因为他们可能仅仅希望将你的这份漂亮代码的一部分植入自己的应用中。
另一种方法是将你的代码编译成静态库(library),让其他开发者添加到自己的项目中。然而,这需要你一并公布所有的公开的头文件,实在是非常不方便。
你需要一种简单的方法来编译你的代码,这种方法应该使得你的代码易分享,并且在多个工程中易复用。你需要的是一种方法来打包你的静态库,将所有的头文件放到一个单元中,这样你就可以立刻将其加入到你的项目中并使用。
OS X完美地支持这一点,因为Xcode就提供了一个项目模板,包含着默认构建目标(target)和可以容纳类似于图片、声音、字体等资源的文件。你可以为iOS创建Framework,不过这是一个比较复杂的手工活,如果你跟着教程走,你将学到怎么样跨过路障,顺利地完成Framework的创建。
.a和.framework的异同
可以参考这篇文章.a和.framework的区别。
一、什么是库?
库是共享程序代码的方式,一般分为静态库和动态库。
二、静态库与动态库的区别?
静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。
动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。
三、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暴露出来就可以了。
可以看出.a的封装和.framework的封装差不多,也有模拟器和真机合并的过程,通过上边的图片我们可以看出.a 和.framework的区别,就是.a+.h+soureFile=.framework。可以看出我们直接封装.framework其实是最好的。那么我们就来看看framework怎么封装的。
另外关于.a的封装大家可以参考iOS如何生成.a文件。
目标
本文将基于Xcode10创建一个简单的工程来教大家如何制作一个自己的framework,目的就是简单易学的制作framework。这种方法可以使得你的代码易分享,在多个工程中复用,并且可以隐藏实现细节,控制公开的头文件。
屏幕快照 2018-10-29 下午5.25.53.png
创建完了FrameWork,我们看看这个FrameWork的结构:
屏幕快照 2018-10-29 下午5.37.46.png
我在里面简单的添加了Dog这个类,看看在这个类里我写了什么内容。
#import "Dog.h"
@implementation Dog
- (void)say{
NSLog(@"I'm a dog.");
}
@end
接下来对我们的这个.framework静态库进行一些简单的设置,如下图所示:
1、首先是Dead Code Stripping设置为NO,网上对此项的解释如下,大致意思是如果开启此项就会对代码中的”dead”、”unreachable”的代码过滤,不过这个开关是否关闭,似乎没有多大影响,不过为了完整还原framework中的代码,将此项关闭也未曾不可。
2、然后将Link With Standard Libraries关闭,我想可能是为了避免重复链接
3、最后将Mach-O Type设为Static Library,framework可以是动态库也可以是静态库,对于系统的framework是动态库,而用户制作的framework只能是静态库。
1524106618702166.png
接下里就是设置我们有那些头文件是需要公开的,如下图设置:
屏幕快照 2018-10-29 下午5.44.14.png
还要记得把要公开的类添加到我们的FrameWorkTest.h中,比如下面是我们例子中的截图:
屏幕快照 2018-10-29 下午5.46.41.png
最后要做的就是打包制作我们这个FrameWork了:
command+B 按照我们下图的选择,打包出这个FrameWork:
1524106827613782.png
这个时候你就会看到FrameWork项目里的Products文件多了我们的.framework文件。你Show in Finder一下就会看到下面这样的两个文件夹了,一个就是真机一个就是模拟机的:
1524106842593191.png
接下来就是生成我们.framework文件的最后一步了:利用终端把模拟机和真机的文件我们合并成一份:
把上图中我们标注的FrameWorkTest文件进行下面的操作:
在终端中输入命令:lipo -create 模拟机和真机的FrameWorkTest文件路径(直接拉到终端就会显示)-output 真机的FrameWorkTest文件路径
具体的例子我们看下面我们终端中的信息:
屏幕快照 2018-10-29 下午5.49.52.png最后将输出路径生成FrameworkTest文件拷贝替换掉真机模式下FrameworkTest.framework中的FrameworkTest文件就可以了。
这下我们就可以使用了
现在把我们.framework拷贝到我们的测试项目中。
屏幕快照 2018-10-29 下午5.58.19.png
运行一下,大功告成。
屏幕快照 2018-10-29 下午5.59.53.png最后需要注意的是
1、在制作framework或者lib的时候,如果使用了category,则使用改Framework的程序运行category方法时会crash,此时需要在该工程中 other linker flags添加参数 -ObjC
2、带有图片资源的需要把图片打包成Bundle文件,和framework一起拷贝到相应的项目中。
3、公开的类中如果引用的private的类,打包以后对外会报错,找不到那个private的类,需要把那个private的.h放到公开文件中
4、namespace 冲突。静态库用了某第三方库,项目也用了同样的第三方库,在编译的时候就会有 duplicate symbol 错误,因为有两份同样的第三方库。解决办法就是把用到的第三方库加上自定义前缀,包括类名、delegate 协议、常量名,尤其需要注意 Category 的方法名要修改。
参考文档:
1、iOS 封装.framework 以及使用
2、iOS封装功能生成 .framework
网友评论