iOS静态库实战之Framework

字数 1469阅读 60

需求

由于喜欢琢磨一些技术,这块领域其实已经好多年就有人发表相关的技术文章,但是自己没有亲手实战一次还真不能说是自己学到这门技术。前段时间研究了一下并动手做了一个静态库。效果挺好,也达到了我想要的预期结果并运用到了我实际项目中。今天重新翻看了一些资料,发现还有完善的地方,特意记录一下,方便后期查阅。

战前准备之.a与.framework库的区别

.a与.framework库的区别

总结:同一个静态库在不同程序中使用时,每一个程序中都得导入一次,打包时也被打包进去,形成一个程序。而动态库在不同程序中,打包时并没有被打包进去,只在程序运行使用时,才链接载入(如系统的框架如UIKit、Foundation等),所以程序体积会小很多,但是苹果不让使用自己的动态库,否则审核就无法通过。

好了,已经了解了两种类型库的区别之后我们就开始动手制作自己的静态库吧。😄

制作Framework静态库

第一步 创建项目

创建Framework项目

第二步 创建需要封装的类或者将需要封装的第三方类加进项目里面

添加或创建封装类

第三步 修改项目配置

1、设置需要公开的头文件


公开的头文件

2、修改生成的Mach-O格式


Mach-O格式

3、将项目的最低支持系统版本设置成iOS 8,可根据自己实际情况设置

最低支持系统版本

  • 这里需要注意的是公开的头文件里 import 了其他类也得添加到 public 中公开出来。如果不想将 import 的类公开出来,那么在头文件中用@class然后在对应的 .m 文件中再 import

  • 需要注意的是默认的Architectures是不包含armv7s,如果需要支持该架构,需要配置一下


    增加armv7s支持

第四步 创建通用静态库执行脚本

1、创建Target


创建Target

2、创建Run Script脚本

创建Run Script脚本

3、编写执行脚本

# Sets the target folders and the final framework product.
# 如果工程名称和Framework的Target名称不一样的话,要自定义FMKNAME

# ----这种方式仅仅适合非pods形式的打包---

# 例如: FMK_NAME = "MyFramework"
FMK_NAME=${PROJECT_NAME}
# FMK_NAME = "TestFamework"
# Install dir will be the final output to the framework.
# The following line create it in the root folder of the current project.
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
# Working dir will be deleted after the framework creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
# -configuration ${CONFIGURATION}
# Clean and Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build

xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build

# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
rm -r "${WRK_DIR}"
open "${INSTALL_DIR}"

第五步 选中新建的Target,Run,如果没有异常的话,会自动弹出生成的Framework文件

生成静态库

制作Framework静态库,同时引用第三方类库

我们有时候封装一个静态库可能会引用到第三方的类库,这个时候,如果我们直接将类库封装进入静态库里面的话,刚好其他工程里面也存在这个类库,那么就容易引起冲突。解决的方案也是有的:
方案1:直接修改其中一个类库重命名(这种方式不是很好)
方案2:分离类库,不将第三方类库打入静态库类,只保留引用(此方式要求其他工程手动引入第三方类库)

下面我会以方案2进行实战讲解。

新建工程的步骤同上面是一样的,这里就不多讲,直接从引入第三方类库开始。

方式一:直接拖拽第三方类库到工程并生成静态库

1、将需要的类库拖拽进工程里面


第三方

2、直接在需要使用的地方导入头文件#import "MBProgressHUD.h"

导入头文件并实现相关方法

3、接下来就是跟之前一样用脚本打包的方式生成对应的通用静态库

方式二:通过CocoaPods方式引用第三方类库并生成静态库

1、跟平时使用CocoaPods方式一样,我们在Podfile文件里面写上需要使用的第三方类库

platform :ios, "9.0"
    
target 'TestFramework' do
    pod 'MBProgressHUD'
end

2、之后我们配置下Scheme


配置Scheme

3、分别选择模拟器跟真机编译两个不同版本静态库


编译静态库

4、将编译好的两个.framework静态库用指令合并成一个

lipo -create xFramework-iphoneos.framework/xFramework xFramework-iphonesimulator.framework/xFramework -output /Users/superdanny/Downloads/framework/xFramework(xFramework为合成后的静态库名称)

这里需要注意一点,当我们的-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支持哪些架构,相关指令格式如下:

# 验证Framework
$ lipo -info /Users/.../xFramework.framework/xFramework
# 验证.a
$ lipo -info /Users/.../libXYPlatform.a
# 没有添加armv7s之前的支持架构
$ lipo -info /Users/superdanny/Out/动态包/CoreAppStatus/Products/CoreAppStatus.framework/CoreAppStatus
$ Architectures in the fat file: /Users/superdanny/Out/动态包/CoreAppStatus/Products/CoreAppStatus.framework/CoreAppStatus are: armv7 i386 x86_64 arm64
# 添加armv7s之后的支持架构
$ lipo -info /Users/superdanny/Out/动态包/CoreAppStatus/Products/CoreAppStatus.framework/CoreAppStatus
$ Architectures in the fat file: /Users/superdanny/Out/动态包/CoreAppStatus/Products/CoreAppStatus.framework/CoreAppStatus are: armv7 armv7s i386 x86_64 arm64

应用

我们新建一个工程Test-Framework,然后集成我们的静态库,编写测试用例。

集成并测试

来看看最后集成静态库Demo展示效果:


效果

参考资料

iOS中.a与.framework库的区别
Xcode 6制作动态及静态Framework
关于ios开发framework及.a文件支持架构判断以及合并
iOS Xcode9 封装生成.framework
IOS-静态库(.a、framewrok)、动态库(.tbd、framework)、Bundle制作(适用于静态库的)研究


再一次感谢您花费时间阅读这篇文章!

微博: @Danny_吕昌辉
博客: SuperDanny

推荐阅读更多精彩内容