前言如果你想将你开发的控件与别人分享,一种方法是直接提供源代码文件。然而,这种方法并不是很优雅。它会暴露所有的实现细节,而这些实现你可能并不想开源出来。此外,开发者也可能并不想看到你的所有代码,因为他们可能仅仅希望将你的这份漂亮代码的一部分植入自己的应用中。 另一种方法是将你的代码编译成静态库(library),让其他开发者添加到自己的项目中。然而,这需要你一并公布所有的公开的头文件,实在是非常不方便。 你需要一种简单的方法来编译你的代码,这种方法应该使得你的代码易分享,并且在多个工程中易复用。你需要的是一种方法来打包你的静态库,将所有的头文件放到一个单元中,这样你就可以立刻将其加入到你的项目中并使用。 OS X完美地支持这一点,因为Xcode就提供了一个项目模板,包含着默认构建目标(target)和可以容纳类似于图片、声音、字体等资源的文件。你可以为iOS创建Framework,不过这是一个比较复杂的手工活,如果你跟着教程走,你将学到怎么样跨过路障,顺利地完成Framework的创建。 比较可以参考这篇文章.a和.framework.a和.framework的区别。 我们可以看出.a的封装和.framework的封装差不多,也有模拟器和真机合并的过程,通过上边的图片我们可以看出.a 和.framework的区别,就是.a .h soureFile=.framework。可以看出我们直接封装.framework其实是最好的。那么我们就来看看framework怎么封装的。 另外关于.a的封装大家可以参考iOS如何生成.a文件 目标本文将基于Xcode7创建一个简单的工程,通过两种方法来教大家如何制作一个自己的framework,目的就是简单易学的制作framework。这种方法可以使得你的代码易分享,在多个工程中复用,并且可以隐藏实现细节,控制公开的头文件。 步骤1、打开Xcode,新建工程。 不要选择“Application”,选择“Framework & Library”。选择第一个,然后Next。 2、创建功能类。 这里我创建一个继承自NSObject的SayHello类 3、实现功能。 在新创建的类里面声明方法并实现。这里我写一个sayHello的方法,以便后面测试使用。 4、更改参数 在TARGETS下选中工程,在Build Settings下更改几个参数。 5、增加armv7s 在Architectures下增加armv7s,并选中。将Build Active Architecture Only 设置为NO。 6、设置Headers 将你要公开的头文件拖至Public下,要隐藏的放在Private或者Project下,当然,隐藏的头文件就无法再被引用。 然后需要在Test.h(必须是公开的,否则无法引用)中将你所有要公开的.h引入。
打包Framework 第一种方法1.选中模拟器,编译程序 2.选中测试机,编译程序 3.在finder中找到framework文件 选中图中所标示的framework,然后右键show in finder。
找到下图中所示的Test文件,一个是Debug-iphoneos(真机)下的,一个是Debug-iphonesimulator(模拟器)下的。 4.通过终端命令将两个framework合为一个模拟器和真机都可使用的framework。 打开控制台输入 lipo -create iphoneos下frameworkTest的路径 simulator下frameworkTest的路径 -output 新的路径,这样就完成了模拟器和真机版本的合并,新路径下的frameworkTest就是你合并后的文件,将这个文件名字改成和你未合并之前的Test一样的名字,放到framework文件夹下,替换掉原来的frameworkTest文件。 上边说的乱糟糟的,看不清楚,这里给大家解释一下,看下边的图:打开终端,手动输入画红线的lipo -create命令,然后绿线是iphoneos下frameworkTest的路径(找到iphoneos下frameworkTest的文件,拖拽进来),会自动有空格,紫线是simulator下frameworkTest的路径(同样找到simulator下frameworkTest的文件,拖拽进来),也会自动有空格,然后输入-output,然后敲空格,在引入一个新的路径(拖拽进一个新的路径),最后敲回车。这样就完成合并了。 上面这段命令就是把真机和模拟器的frameworkTest合并成一个MyNewFrameworktest文件并存放在桌面上的New文件夹下。 这里我们合并的时候会遇到一个error,这是啥原因还真不知道,但是会在和我们-output的文件夹路径并列的地方生成一个.lipo文件,这个.lipo文件我们下边会说到。 注意:合并完成后会出现一个如下图的.lipo格式的文件。 这TM是啥,不是应该出现一个类似下图的吗?不应该后缀什么也没有吗?怎么后缀会是.lipo,这是什么文件啊?! 我们的操作是按照人家说的把合成后的文件名字改成MyFrameworkTest替换原来的。而且,把后缀.lipo去掉! 在按照上述说的,替换了原来的。 然后就可以进行下一步了。 5.将修改后的framework拷贝出来保存,这就是我们最终制作的framework。 第二种方法1、选中TARGETS下的工程,点击上方的Editor,选择Add Target创建一个Aggregate. 2、选择Other下的Aggregate,点击Next创建。 3、嵌入脚本。选中刚刚创建的Aggregate,然后选中右侧的Build Phases,点击左下方加号,选择New Run Script Phase 将这段脚本复制进去:
这里有一个误区,就是复制上边的这段脚本的时候,会在我们期望的效果里面多了几个回车,这几个回车是致命的,如果不删除回车,会报出如下的错误: 最后的格式如下图,尽量一个回车也不能错: 通过第一种方法中“把真机和模拟器的frameworkTest合并成一个”的过程和上边的脚本语言比较,我们可以发现其实两者异路同归,两个方法里面同时用到了“lipo -create xxx”和“-output xxx”,不同的地方是第一种方法需要我们自己真机和模拟器分别变异一遍,而且需要我们把framework的路径拖进去,相比而言第二种方法比较简单。 4、编译。如图所示,command B编译。这里Generic iOS Device的意思是“iOS通用设备”,大概就是说模拟器和真机都能用。 5、编译成功后会自动跳出一个finder,保存这个.framework,这就是我们需要的framework。 至此,两种打包framework的方法介绍完成!
最后就是用我们的Framework了,倒入另一个Xcode中,我们打开这个framework看看,发现只有Headers,里面有两个.h,其中一个是我们之前添加的FrameworkDemo.h文件,另一个就是我们的SayHello.h 。 然后引入头文件: 由于我们测试的方法是实例方法,那么我们实例化一个实例对象,然后就可以让这个实例对象调取相应的方法了: 至此,完成Framework的制作和使用。
总结最后需要注意的是:
补充编译过程: 从C代码到可执行文件经历的步骤是:源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件 在最后一步需要把.o文件和C语言运行库链接起来,这时候需要用到ld命令。源文件经过一系列处理以后,会生成对应的.obj文件,然后一个项目必然会有许多.obj文件,并且这些文件之间会有各种各样的联系,例如函数调用。链接器做的事就是把这些目标文件和所用的一些库链接在一起形成一个完整的可执行文件。Other linker flags设置的值实际上就是ld命令执行时后面所加的参数 下面逐个介绍3个常用参数: -ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中 -all_load:会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force_load参数。 -force_load:所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载
后期会试着把贝塞尔画饼的demo封装成framework,另外可能会增加Bundle文件的生成方法。 参考自1、iOS-制作Framework(最新)
最后,哪里不对的地方可以给我留言,我会及时改进的,谢谢大家。 |
|