一、什么是 SDK?
SDK是软件开发工具包,iOS中称为库
二、SDK 设计的基本原则
- SDK 安全,稳定
- 统一的开发规范
- Library 小而精
- 不依赖第三方 SDK
iOS环境中的SDK
什么是Framework?
Framework是程序中使用的一种资源打包方式,可以将代码文件、头文件、资源文件等集中在一起,方便开发者使用。和静态库动态库的本质是没有什么关系。
静态库和动态库的区别
- 动态库
链接时不复制,而是在程序启动后动态加载,供程序调用,变现形式为.dylib和.framework
-
优点: 1.系统只加载一次,多个程序共用,节省内存
-
缺点: 动态库依赖于外部环境,如环境缺少动态库或者库的版本不正确
-
- 静态库
链接时会被完整的复制到可执行文件中,多次使用多次拷贝,表现形式.a 和.Framework
- 优点 目标程序没有外部依赖,直接就可以运行,效率比较高
- 缺点 使用静态库程序的体积增大
a与.framework有什么区别?
.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件,.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。.a + .h + sourceFile = .framework
制作SDK
第一步:创建 App 工程,命名为 WatchDemo
第二步:在WatchDemo目录下创建Framework工程,命名为WatchSDK
第三步:设置 Framework 工程的 Build Settings
第四步:创建 WorkSpace,命名为 WatchDemo
第五步:连接 Framework 工程和 App 工程
打开 WatchDemo.xcworkspace是空的,我们需要把WatchSDK.xcodeproj和 WatchDemo.xcodeproj拖进来
第六步:把 Framework 添加到 App 工程中
用 WorkSpace 把两个工程连接起来
第七步:给 Framework 加点功能 我们需要增加一个 TGPerson 类,定义一个 walk 方法,实现里面打印一句话“吃完饭去散步”。然后修改 TGPerson.h 的 Target Membership 为 Public,意思为公开头文件。
TGPerson 实现
@implementation TGPerson
+ (void)walk {
NSLog(@"吃完饭去散步")
}
@end
第八步:暴露SDK头文件
第九步:在 App 的 ViewController 调用一下 SDK 的方法
#import "ViewController.h"
#import <WatchSDK/WatchSDK.h>
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[TGPerson walk];
}
@end
第十步:运行一下,可以发现App工程成功调用了SDK的方法
使用脚本合并真机、模拟器等多种架构的 Framework
第一步:添加一个 Aggregate Target
第二步:将 Aggregate Target 命名为“WatchSDK-Script”
第三步:依赖 WatchSDK
第四步:添加脚本
通用脚本,复制粘贴即可:
# Type a script or drag a script file from your workspace to insert its path.
UNIVERSAL_OUTPUTFOLDER=../Framework/
# 创建输出目录,并删除之前的framework文件
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
rm -rf "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework"
# 分别编译模拟器和真机的Framework
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
# 定义真机、模拟器Build文件夹路径变量
IPHONE_BUILD=${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
SIMULATOR_BUILD=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework
# 拷贝framework到univer目录
cp -R "${IPHONE_BUILD}" "${UNIVERSAL_OUTPUTFOLDER}/"
#记录真机架构路径位置
#echo "${IPHONE_BUILD}" > "${UNIVERSAL_OUTPUTFOLDER}/file.txt"
#打开真机架构路径
open "${IPHONE_BUILD}"
#cp -R "${SIMULATOR_BUILD}" "${UNIVERSAL_OUTPUTFOLDER}/"
# 定义输出路径变量
OUTPUT_PATH=${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework
# 合并framework,输出最终的framework到build目录
lipo -create "${IPHONE_BUILD}/${PROJECT_NAME}" "${SIMULATOR_BUILD}/${PROJECT_NAME}" -output "${OUTPUT_PATH}/${PROJECT_NAME}"
第五步:去除模拟器的 arm64 架构
iOS12 模拟器增加了arm64架构 ,不去除会报真机模拟器库无法合并的错误:have the same architectures (arm64) and can't be in the same fat output file
第六步:运行脚本
Framework 基础配置
- 配置SDK支持最低版本
- 配置SDK为静态库
- 配置
Enable Bitcode
- 配置SDK
Bulid Configuration
- 配置
Other Linker Flags,添加-ObjC
Bundle 文件
修改bundle配置
- 修改
Base SDK为iOS否则编译无法通过
- 修改
COMBINE_HIDPI_IMAGES为No否则Bundle中的图片就是tff格式
- 删除安装路径
Installation Directory的值,资源包不需要安装
生成bundle文件
- 向bundle中添加资源
- 编译bundle中资源
- 将bundle资源放到宿主工程中