美文网首页CocoaPodsiOS 功能展示
iOS生成 .framework以及使用 .framework

iOS生成 .framework以及使用 .framework

作者: 水灵芳蕥 | 来源:发表于2018-06-21 14:53 被阅读28次

    前言

    如果你想将你开发的控件与别人分享,一种方法是直接提供源代码文件。然而,这种方法并不是很优雅。它会暴露所有的实现细节,而这些实现你可能并不想开源出来。此外,开发者也可能并不想看到你的所有代码,因为他们可能仅仅希望将你的这份漂亮代码的一部分植入自己的应用中。

          另一种方法是将你的代码编译成静态库(library),让其他开发者添加到自己的项目中。然而,这需要你一并公布所有的公开的头文件,实在是非常不方便。

    你需要一种简单的方法来编译你的代码,这种方法应该使得你的代码易分享,并且在多个工程中易复用。你需要的是一种方法来打包你的静态库,将所有的头文件放到一个单元中,这样你就可以立刻将其加入到你的项目中并使用。

          OS X完美地支持这一点,因为Xcode就提供了一个项目模板,包含着默认构建目标(target)和可以容纳类似于图片、声音、字体等资源的文件。你可以为iOS创建Framework,不过这是一个比较复杂的手工活,如果你跟着教程走,你将学到怎么样跨过路障,顺利地完成Framework的创建。

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

    目标

    本文将创建一个简单的工程,通过两种方法来教大家如何制作一个自己的framework,目的就是简单易学的制作framework。这种方法可以使得你的代码易分享,在多个工程中复用,并且可以隐藏实现细节控制公开的头文件

    步骤

    1、打开Xcode,新建工程。

    不要选择“Application”,选择“Framework & Library”。选择第一个,然后Next,创建ffffffffff

    2、创建功能类。

    这里我创建一个继承自NSObject的SayHello类

    3、实现功能。

    在新创建的类里面声明方法并实现。这里我写一个sayHello的方法,以便后面测试使用。

    4、更改参数

    在TARGETS下选中工程,在Build Settings下更改几个参数。

    5、增加armv7s

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

    6、设置Headers

    将你要公开的头文件拖至Public下,要隐藏的放在Private或者Project下,当然,隐藏的头文件就无法再被引用。 

    然后需要在ffffffffff.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文件并存放在桌面上的nnnnnnnnn文件夹下。

    这里我们合并的时候会遇到一个error,这是啥原因还真不知道,但是会在和我们-output的文件夹路径并列的地方生成一个.lipo文件。

    我们的操作是按照人家说的把合成后的文件名字改成MyFrameworkTest替换原来的。而且,把后缀.lipo去掉!

    在按照上述说的,替换了原来的。

    然后就可以进行下一步了。

    5.将修改后的framework拷贝出来保存,这就是我们最终制作的framework。

    到此打包完成,下面介绍使用。

    .framework的使用

    在新项目中导入

    导入头文件

    至此,完成Framework的制作和使用。

    总结

    最后需要注意的是:

    1、.h文件的外漏一定要保证是自己的想要外漏的。不想外漏的就别外漏了。

    2、开始打包的时候,一定要在选中模拟器和选中真机上边分别编译一次, 我觉得之前在家里没有真机的时候编译的好像不对。

    3、在终端上边合并的时候可能是error并生成一个.lipo文件,不要怕,大胆修改成同名的不挂后缀的同名文件。

    4、调用的时候分清楚是类方法还是实例方法,方便调用。

    5、在制作framework或者lib的时候,如果使用了category,则使用改FMWK的程序运行时会crash,此时需要在该工程中 other linker flags添加两个参数 -ObjC -all_load。(这点没有亲测)

    6、带有图片资源的需要把图片打包成Bundle文件,和framework一起拷贝到相应的项目中。

    7、公开的类中如果引用的private的类,打包以后对外会报错,找不到那个private的类,可以把那个private的.h放到(也没亲测)

    8、namespace 冲突。静态库用了某第三方库,项目也用了同样的第三方库,在编译的时候就会有 duplicate symbol 错误,因为有两份同样的第三方库。解决办法就是把用到的第三方库加上自定义前缀,包括类名、delegate 协议、常量名,尤其需要注意 Category 的方法名要修改。

    9、封装静态库的时候应尽量避免引入重量级第三方库,多自己进行封装

    10、一个静态库要有自己独有的前缀,所有类名、常量等都要加同样的前缀。

    11、真机+模拟器支持。(和第2条意思一样)Xcode 默认只会用当前环境(真机或模拟器)生成静态库,这样的 SDK 不方便其他项目开发时调试。解决办法就是通过脚本生成一份通用库,build_universal_library.sh,via SO.

    12、文档。静态库的方便是使用者直接拿你提供的方法来用,无需关注具体实现;不方便在于看不到实现,出现问题无法排查,因此需要把 SDK 的版本、更新历史、使用、FAQ 等写成文档,方便使用,也显得 SDK 比较正式规范。

    13、图片等资源文件用 bundle 方式打包。一个简单制作 bundle 的方法:新建文件夹,重命名为 YourSDK.bundle,然后 Show Package Contents 打开,加入图片。使用图片的时候需要指明 bundle: [UIImage imageNamed:@"YourSDK.bundle/img.png"]。也可以用 Target 方式制作 bundle,比如 iOS Library With Resourceshttp://www.galloway.me.uk/tutorials/ios-library-with-resources/.

    14、如果 SDK 有用到 Category,注意项目设置 Other Linker Flags 添加 -ObjC。(后边介绍了-ObjC的作用)

    补充

    编译过程:

    从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需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载

    相关文章

      网友评论

        本文标题:iOS生成 .framework以及使用 .framework

        本文链接:https://www.haomeiwen.com/subject/qywqyftx.html