需求
由于喜欢琢磨一些技术,这块领域其实已经好多年就有人发表相关的技术文章,但是自己没有亲手实战一次还真不能说是自己学到这门技术。前段时间研究了一下并动手做了一个静态库。效果挺好,也达到了我想要的预期结果并运用到了我实际项目中。今天重新翻看了一些资料,发现还有完善的地方,特意记录一下,方便后期查阅。
战前准备之.a与.framework库的区别
总结:同一个静态库在不同程序中使用时,每一个程序中都得导入一次,打包时也被打包进去,形成一个程序。而动态库在不同程序中,打包时并没有被打包进去,只在程序运行使用时,才链接载入(如系统的框架如UIKit、Foundation等),所以程序体积会小很多,但是苹果不让使用自己的动态库,否则审核就无法通过。
好了,已经了解了两种类型库的区别之后我们就开始动手制作自己的静态库吧。😄
制作静态库时的几点注意
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暴露出来就可以了。
制作Framework静态库
第一步 创建项目
第二步 创建需要封装的类或者将需要封装的第三方类加进项目里面
第三步 修改项目配置
1、设置需要公开的头文件
2、修改生成的Mach-O格式
3、将项目的最低支持系统版本设置成iOS 8,可根据自己实际情况设置
这里需要注意的是公开的头文件里 import 了其他类也得添加到 public 中公开出来。如果不想将 import 的类公开出来,那么在头文件中用@class然后在对应的 .m 文件中再 import。
需要注意的是默认的Architectures是不包含armv7s,如果需要支持该架构,需要配置一下
第四步 创建通用静态库执行脚本
1、创建Target
2、创建Run Script脚本
3、编写执行脚本
|
|
第五步 选中新建的Target,Run,如果没有异常的话,会自动弹出生成的Framework文件
制作Framework静态库,同时引用第三方类库
我们有时候封装一个静态库可能会引用到第三方的类库,这个时候,如果我们直接将类库封装进入静态库里面的话,刚好其他工程里面也存在这个类库,那么就容易引起冲突。解决的方案也是有的:
方案1:直接修改其中一个类库重命名(这种方式不是很好)
方案2:分离类库,不将第三方类库打入静态库类,只保留引用(此方式要求其他工程手动引入第三方类库)
下面我会以方案2进行实战讲解。
新建工程的步骤同上面是一样的,这里就不多讲,直接从引入第三方类库开始。
方式一:直接拖拽第三方类库到工程并生成静态库
1、将需要的类库拖拽进工程里面
2、直接在需要使用的地方导入头文件#import "MBProgressHUD.h"
3、接下来就是跟之前一样用脚本打包的方式生成对应的通用静态库
方式二:通过CocoaPods方式引用第三方类库并生成静态库
1、跟平时使用CocoaPods方式一样,我们在Podfile
文件里面写上需要使用的第三方类库
|
|
2、之后我们配置下Scheme
3、分别选择模拟器跟真机编译两个不同版本静态库
4、将编译好的两个.framework
静态库用指令合并成一个
|
|
这里需要注意一点,当我们的-output
导出路径参数设置不同时,产生的结果也会不同。
结果1:比如有/Users/superdanny/Downloads/framework
这个目录的时候,将导出路径参数设置为/Users/superdanny/Downloads/framework
。那么就会产生一个跟framework
文件夹同级且同名的framework.lipo
的文件。同时终端也会报一个错误,这种情况,我们只需要将后缀.lipo
去掉,并且将文件名改为静态库名称。然后执行下文图片中说到的替换操作。
结果2:同样有/Users/superdanny/Downloads/framework
这个目录的时候,但是我们将导出路径参数设置为/Users/superdanny/Downloads/framework/xFramework
。此时就会在framework
文件夹下产生一个名为xFramework
的文件。之后我们直接执行下文图片中说到的替换操作即可。
正确的做法应该是用第二种。
指令参数说明
参数 | 说明 |
---|---|
xFramework-iphoneos.framework/xFramework | 真机静态库 |
xFramework-iphonesimulator.framework/xFramework | 模拟器静态库 |
/Users/superdanny/Downloads/framework/xFramework | 合成后文件存放路径 |
大功告成!🎉
验证
最后我们来验证下Framework支持哪些架构,相关指令格式如下:
|
|
|
|
应用
我们新建一个工程Test-Framework
,然后集成我们的静态库,编写测试用例。
来看看最后集成静态库Demo展示效果:
参考资料
iOS中.a与.framework库的区别
Xcode 6制作动态及静态Framework
关于ios开发framework及.a文件支持架构判断以及合并
iOS Xcode9 封装生成.framework
IOS-静态库(.a、framewrok)、动态库(.tbd、framework)、Bundle制作(适用于静态库的)研究
再一次感谢您花费时间阅读这篇文章!
微博: @Danny_吕昌辉
博客: SuperDanny