iOS Framework 制作

780 阅读3分钟

一、什么是 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

image.png

第二步:在WatchDemo目录下创建Framework工程,命名为WatchSDK

image.png

第三步:设置 Framework 工程的 Build Settings

image.png

第四步:创建 WorkSpace,命名为 WatchDemo

image.png

image.png

第五步:连接 Framework 工程和 App 工程 打开 WatchDemo.xcworkspace是空的,我们需要把WatchSDK.xcodeproj和 WatchDemo.xcodeproj拖进来 image.png

image.png

第六步:把 Framework 添加到 App 工程中

用 WorkSpace 把两个工程连接起来 image.png

第七步:给 Framework 加点功能 我们需要增加一个 TGPerson 类,定义一个 walk 方法,实现里面打印一句话“吃完饭去散步”。然后修改 TGPerson.h 的 Target Membership 为 Public,意思为公开头文件。

image.png

TGPerson 实现

@implementation TGPerson

+ (void)walk {
    NSLog(@"吃完饭去散步")
}

@end

第八步:暴露SDK头文件

image.png

第九步:在 App 的 ViewController 调用一下 SDK 的方法

#import "ViewController.h"
#import <WatchSDK/WatchSDK.h>

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [TGPerson walk];
}

@end

第十步:运行一下,可以发现App工程成功调用了SDK的方法

image.png

使用脚本合并真机、模拟器等多种架构的 Framework

第一步:添加一个 Aggregate Target

image.png

第二步:将 Aggregate Target 命名为“WatchSDK-Script”

image.png

第三步:依赖 WatchSDK

image.png

第四步:添加脚本

image.png

image.png

通用脚本,复制粘贴即可:

# 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

image.png

第六步:运行脚本

Framework 基础配置

  • 配置SDK支持最低版本

image.png

  • 配置SDK为静态库

image.png

  • 配置Enable Bitcode

image.png

  • 配置SDK Bulid Configuration

image.png

  • 配置Other Linker Flags,添加-ObjC

image.png

Bundle 文件

image.png

image.png

image.png

修改bundle配置

  • 修改 Base SDK 为 iOS 否则编译无法通过

image.png

  • 修改COMBINE_HIDPI_IMAGES 为 No 否则Bundle中的图片就是tff格式

image.png

  • 删除安装路径 Installation Directory 的值,资源包不需要安装 image.png

生成bundle文件

  • 向bundle中添加资源

image.png

  • 编译bundle中资源

image.png

  • 将bundle资源放到宿主工程中 image.png