最近也是刚刚写完一个SDK,想起好久都没有更新技术博客了,这个月给自己的目标是更新五篇,所以会把之前的学习笔记再认真的整理以后发表。
说起framework,在我们实际开发中使用的很频繁可是又知之甚少,到底是什么原因让我们如此陌生,现在就来带你研究。
framework其实它是一种更深层次的封装,通过良好的封装和细致阅读文档,我们可以快速的掌握SDK中最核心工具的操作。
关于心得我会放在后面来说,下面我们开始进入构造framework工程中去吧!
1.新建framework工程
2.设置sdk版本号
3.buildSettings设置:Build Active Architecture Only(No)、mach-o type(static library)
4.环境 release
5.创建 run script并导入脚本
# 使用方法:在framework工程中,TARGETS-Build Phases-加号-New Run Script Phase,
# 粘贴脚本,分别选择真机和模拟器各编译一次即可,成功合并后会在finder中打开。
# (很多教程写新建一个Aggregate Target再添加脚本,但是
# 由于默认已经有一个与项目名相同的TARGET,不能重名,如果又要保持framework名称一致
# 又需要修改,不如这样方便。)
# 用到的xcode环境变量: 参考https://www.jianshu.com/p/b5c85dcd6b04
# ${SRCROOT} 项目根目录
# ${PROJECT_NAME} 项目名
# ${BUILD_ROOT} 编译输出根目录,通常为~/Library/Developer/Xcode/DerivedData/项目名-乱七八糟的字符串/Build/Products
# ${CONFIGURATION} release或debug
# ${ACTION} 编译时为build
# 真机编译时生成的framework位置
DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
# 模拟器编译时生成的framework位置
SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework
# 定义合并后framework的存放位置 这里放在项目根目录
INSTALL_DIR=${SRCROOT}/${PROJECT_NAME}.framework
# build时执行,且两类cpu架构均已编译成功生成framework
if [ "${ACTION}" = "build" ] && [ -d "${DEVICE_DIR}" ] && [ -d "${SIMULATOR_DIR}" ]
then
# 删除原有的合并文件(.framework其实是个文件夹)
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
# 新建合并文件
mkdir -p "${INSTALL_DIR}"
# 将真机framework拷贝至合并文件(因为后面的lipo -create只合并输出.framework下的"项目名"二进制文件,
# 还需要剩余的其他文件才能被使用,本脚本以真机framework的为基准,
# 这一步合并了Modules/xxx.swiftmodule文件夹,以及下面提到的Headers/xxx-Swift.h
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
# 利用lipo合并两个.framework里的二进制文件,结果保存在合并后目录
lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"
# ***如果是swift工程,还需要拷贝.swiftmodule下的文件
SIMULATOR_SWIFT_MODULES_DIR=${SIMULATOR_DIR}/Modules/${PROJECT_NAME}.swiftmodule/.
if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]
then
cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${INSTALL_DIR}/Modules/${PROJECT_NAME}.swiftmodule"
fi
# *** xcode10.2以后,如果包含Swift文件,
# 还需要合并处理xx.framework/Headers/PROJECT_NAME-Swift.h里的内容
SIMULATOR_SWIFT_HEADER_FILE=${SIMULATOR_DIR}/Headers/${PROJECT_NAME}-Swift.h
DEVICE_SWIFT_HEADER_FILE=${DEVICE_DIR}/Headers/${PROJECT_NAME}-Swift.h
INSTALL_SWIFT_HEADER_FILE=${INSTALL_DIR}/Headers/${PROJECT_NAME}-Swift.h
if [ -e "${SIMULATOR_SWIFT_HEADER_FILE}" ] && [ -e "${DEVICE_SWIFT_HEADER_FILE}" ]
then
# 合并-Swift.h
# 写入.h文件
echo "#if TARGET_OS_SIMULATOR" > "${INSTALL_SWIFT_HEADER_FILE}"
# 模拟器
cat "${SIMULATOR_SWIFT_HEADER_FILE}" >> "${INSTALL_SWIFT_HEADER_FILE}"
echo "#else" >> ${INSTALL_SWIFT_HEADER_FILE}
# 真机
cat "${DEVICE_SWIFT_HEADER_FILE}" >> "${INSTALL_SWIFT_HEADER_FILE}"
echo "#endif" >> "${INSTALL_SWIFT_HEADER_FILE}"
fi
# 合并-Swift.h结束
# 打开项目目录,得到合并后的.framework
open "${SRCROOT}"
fi
复制代码
6.buildPhases设置 Headers文件访问权限 project私人的, public公开的
7.使用pod导入第三方依赖
这里我是使用的pod管理,定义好podspec文件内容,然后通过本地导入的方法,好处是当我们执行pod install命令时,会帮我们一起拉取SDK中对应的第三方库,如果项目已经存在的第三方库,也不会影响主项目的库,最后还是需要注意好库的版本问题就可以了。
8.将关键代码拖入工程
9.分别在虚拟机和真机Building
10.完成
后话
在参照了其它平台的SDK,包括问询了朋友的意见,给我的感觉是OC语法更适用于SDK的开发,因为其天生的.hm文件分离,使我们保护了内部实现不被暴露出来,但是技术就是要有探索精神,最后我还是选择了使用swift来编写SDK,只要还没有放弃就有机会看到真相。
说回SDK,虽然创建项目是一尘不变的,但是每个人走路的不同就形成了不同的经验:
做好重要业务的私有化和加密性测试,理解不同,见仁见智
提前做好适配多环境使用的计划,如iOS/iPad、swift/OC
设置好需要外部暴露的属性和方法,不需要的部分可以不展示出来,尽量保持整洁
考虑方法回调的全面性,这里可以写活一点给使用者更开放灵活的空间
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END