一、framework 与 .a
1.为什么要使用静态库
方便共享代码,便于合理使用。
实现iOS程序的模块化。可以把固定的业务模块化成静态库。
和别人分享你的代码库,但不想让别人看到你代码的实现。
开发第三方sdk的需要
2..a与framework的区别
.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。
.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。
.a + .h + sourceFile = .framework。
库是共享程序代码的方式,一般分为静态库和动态库。
静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。 iOS中静态库形式: .a和.framework
动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。 iOS中动态库形式: .dylib和.framework
系统的.framework是动态库,我们自己建立的.framework是静态库
二、framework的制作
1.创建工程
截屏2021-09-07 上午10.25.44.png2.把需打包项目拖进创建好的工程里
1630982660041.jpg蓝框为需要打包的项目,红框为原始文件
3.修改项目的几处配置信息
1)将bitcode置为NO
2)选择工程->targe->build setting 进行如下设置
将Build Active Architecture Only 设为 NO
将Mach-O Type 设为 Static Library
将Dead Code stripping 设为No
4.项目暴露文件配置
把要公开的头文件已到Public中去,在使用.framework时只能调用公开.h文件中的声明
截屏2021-09-07 上午11.16.53.png
完成上述步骤之后,在TestFramework.h文件中,把所有需要暴露的.h文件都用#import < TestFramework/TestFramework.h>引入,记住一定要将所有的需要暴露的.h文件都写在给定位置,不然编译后生成的.framework在引用的时候会有警告;
5.编译生成framework
1)开始编译,选择Generic iOS Device 或者 真机 或 模拟器,编译一下,再选择模拟器环境编译一下,此时show in find项目根目录会多一个build文件里面包含真机和模拟器framework
截屏2021-09-07 上午11.22.30.png
2)合并两个包命令行执行如下操作
lipo -create 真机库路径(../TestFramework.framework/TestFramework) 模拟库路径 -output 导出路径
截屏2021-09-07 上午11.26.39.png会生成一个.lipo文件,把它重命名为TestFramework并替换真机或模拟器里的TestFramework文件
此时就是合并后的framework包
6.脚本生成framework包
target下点击+
1630985374227.jpg 1630985398757.jpg
在上图出添加脚本,命令如下然后选择Any ios Device 执行Commond + B
#!/bin/sh
# 取得build的target名(get project name)
TARGET_NAME=${PROJECT_NAME}
if [[ $1 ]]
then
TARGET_NAME=$1
fi
UNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/${PROJECT_NAME}/"
#创建输出目录,并删除之前的framework文件
mkdir -p "${UNIVERSAL_OUTPUT_FOLDER}"
rm -rf "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework"
# 设置真机和模拟器生成的静态库路径 (set devcie framework and simulator framework path)
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
#分别编译模拟器和真机的Framework
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
#拷贝framework到univer目录
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework" "${UNIVERSAL_OUTPUT_FOLDER}"
#合并framework,输出最终的framework到build目录
lipo -create -output "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework/${TARGET_NAME}"
#删除编译之后生成的无关的配置文件
dir_path="${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/"
for file in ls $dir_path
do
if [[ ${file} =~ ".xcconfig" ]]
then
rm -f "${dir_path}/${file}"
fi
done
#判断build文件夹是否存在,存在则删除
if [ -d "${SRCROOT}/build" ]
then
rm -rf "${SRCROOT}/build"
fi
rm -rf "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator" "${BUILD_DIR}/${CONFIGURATION}-iphoneos"
#打开合并后的文件夹
open "${UNIVERSAL_OUTPUT_FOLDER}"
生成包后导入项目即可、如果使用pod 引入的三方库直接在自己项目中添加对应的引用,执行pod install即可
7.testFramework中图片等资源文件的引用
1.创建文件夹修改后缀名为.bundle然后添加图片
2.file->new->新建bundle项目
注:bundle文件需与项目同步导入到所需项目中
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
UIImage *image = [UIImage imageNamed:@"images.bundle/icon_select" inBundle:bundle compatibleWithTraitCollection:nil];
8.framework中使用其他的framework库(以支付宝为例)
新建文件夹找到AlipaySDK.framework里红框AlipaySDK修改其后缀名为.a并copy所有绿框内所有文件到新建的文件夹如下图:
1631090885299.jpg
然后把导入到需要打包的项目中
注:1.如果framework使用categary需在引用的项目中target->build setting->other link flag 中添加 -ObjC
2.若打包的framework使用了三方库,那么引用的项目也需导入三方库所需的系统库
问题点:
1.have the same architectures (arm64) and can't be in the same fat output file
说明:Xcode 12以后模拟器编译生成的framework中也会包含arm64,因此在合并时会报以上错误
解决方法如下:
在 Target->BuildSetting->Architectures->Excluded Architectures ,然后重新编译合并包即可
截屏2022-01-13 上午10.48.40.png
网友评论