iOS 开发中,框架(Framework)是封装可复用代码、资源、逻辑的核心载体,广泛用于项目模块化拆分、团队协作、SDK 开发等场景。本文将从「静态框架 vs 动态框架」的核心区别入手,详解框架的创建、配置、调试、发布全流程,覆盖 Objective-C 和 Swift 两种主流开发语言。
一、核心概念:静态框架 vs 动态框架
在 iOS 中,框架分为静态框架(Static Framework) 和动态框架(Dynamic Framework),核心差异在于链接时机和运行方式:
| 特性 | 静态框架 | 动态框架 |
|---|---|---|
| 链接时机 | 编译期链接到主程序二进制包 | 运行期加载(iOS 8 + 支持 App 内动态加载) |
| 包体积 | 代码合并到主程序,增加 IPA 体积 | 单独存在,可被多个 Target 共享 |
| 上架 / App Store | 无限制 | iOS App 内使用需嵌入,watchOS/tvOS 有限制 |
| 调试便利性 | 修改需重新编译主程序 | 可单独更新(开发阶段更灵活) |
| 典型用途 | 通用工具类、第三方 SDK(如支付、统计) | 项目模块化拆分、动态更新组件 |
注:iOS 系统层面的动态框架(如 UIKit、Foundation)由系统提供,App 内自定义动态框架需嵌入到 App Bundle 中,无法像 macOS 那样独立安装。
二、基础步骤:创建自定义 Framework(Xcode)
以 Xcode 15 为例,分别演示 Objective-C 和 Swift 框架的创建流程:
1. 新建 Framework 项目
- 打开 Xcode → 「Create a new Xcode project」→ 选择「Framework」(iOS 平台)→ 点击「Next」;
- 填写项目信息:
- Product Name:框架名称(如
YYToolKit); - Team:选择开发者团队(无则选 None);
- Language:选择 Objective-C/Swift;
- 取消勾选「Use Core Data」「Include Tests」(按需开启);
- Product Name:框架名称(如
- 选择保存路径 → 点击「Create」,生成框架项目。
2. 框架核心结构解析
生成的项目包含以下关键文件 / 目录:
| 文件 / 目录 | 作用 |
|---|---|
YYToolKit.h |
框架的公共头文件(伞头文件),对外暴露需要公开的类 / 方法 |
Classes/ |
存放框架的核心代码(.h/.m 或 .swift) |
Assets.xcassets |
存放框架的图片、颜色等资源(按需添加) |
Info.plist |
框架的配置文件(版本、Bundle ID、最低系统版本等) |
Build Settings |
编译配置(架构、链接方式、头文件搜索路径等) |
3. 编写框架核心代码
(1)Objective-C 框架
- 新建类:右键「Classes」→ 「New File」→ 「Objective-C Class」(如
YYStringTool); - 实现核心功能(示例:字符串处理):
objc
// YYStringTool.h(公开头文件) #import <Foundation/Foundation.h>@interface YYStringTool : NSObject /// 去除字符串首尾空格和换行 + (NSString *)trimWhitespace:(NSString *)str; @end// YYStringTool.m(私有实现) #import "YYStringTool.h"@implementation YYStringTool + (NSString *)trimWhitespace:(NSString *)str {if (!str) return @"";return [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; } @end - 暴露头文件:打开
YYToolKit.h,添加公开头文件引用:objc#import <YYToolKit/YYStringTool.h>
(2)Swift 框架
- 新建类:右键「Classes」→ 「New File」→ 「Swift File」(如
YYStringTool.swift); - 实现核心功能(注意:Swift 需用
public修饰公开接口):swift// YYStringTool.swift import Foundationpublic class YYStringTool {/// 去除字符串首尾空格和换行public static func trimWhitespace(_ str: String?) -> String {guard let str = str else { return "" }return str.trimmingCharacters(in: .whitespacesAndNewlines)} } - Swift 框架无需手动维护伞头文件,Xcode 会自动生成模块映射(Module Map)。
4. 关键配置(Build Settings)
无论 OC/Swift,需重点配置以下项(Targets → 框架名称 → Build Settings):
| 配置项 | 推荐值(iOS) | 说明 |
|---|---|---|
| Base SDK | iOS Latest (iOS 17) | 基于最新 iOS SDK 编译 |
| iOS Deployment Target | iOS 12.0+(按需调整) | 框架支持的最低 iOS 版本 |
| Mach-O Type | Static Library(静态)/ Dynamic Library(动态) | 框架类型(默认动态,需静态则改为 Static Library) |
| Headers(OC 专属) | Public/Project/Private | 分类管理头文件:Public 对外暴露,Project/Private 仅框架内部使用 |
| Build Libraries for Distribution | YES | (Swift/OC 混编)生成稳定的模块接口,避免编译兼容问题 |
| Enable Bitcode | NO(主流选择) | 大部分第三方 SDK 禁用 Bitcode,统一配置避免冲突 |
三、框架的编译与调试
1. 编译框架
- 选择编译目标:Xcode 顶部选择「Any iOS Device (arm64)」(真机)或「iPhone 15」(模拟器);
- 编译:点击「Product → Build」,编译成功后,框架产物会生成在「DerivedData」目录中:
- 真机产物:
DerivedData/项目名/Build/Products/Release-iphoneos/YYToolKit.framework - 模拟器产物:
DerivedData/项目名/Build/Products/Release-iphonesimulator/YYToolKit.framework
- 真机产物:
2. 合并真机 / 模拟器架构(静态框架)
静态框架若需同时支持真机(arm64)和模拟器(x86_64/arm64),需合并架构:
- 打开终端,执行
lipo命令(替换路径为实际路径):bash运行# 合并架构 lipo -create \ /Users/xxx/Library/Developer/Xcode/DerivedData/YYToolKit/Build/Products/Release-iphoneos/YYToolKit.framework/YYToolKit \ /Users/xxx/Library/Developer/Xcode/DerivedData/YYToolKit/Build/Products/Release-iphonesimulator/YYToolKit.framework/YYToolKit \ -output /Users/xxx/Desktop/YYToolKit# 替换合并后的二进制文件到框架中 cp /Users/xxx/Desktop/YYToolKit /Users/xxx/Desktop/YYToolKit.framework/YYToolKit - 验证架构:
lipo -info /Users/xxx/Desktop/YYToolKit.framework/YYToolKit,输出包含arm64和x86_64即成功。
3. 在主项目中集成框架
方式 1:直接嵌入(开发阶段)
- 将
YYToolKit.framework拖入主项目 → 勾选「Copy items if needed」→ 选择「Create groups」; - 配置主项目:
- Targets → 主项目 → General → Frameworks, Libraries, and Embedded Content → 选择框架 → 「Embed & Sign」(动态框架)/「Do Not Embed」(静态框架);
- 引入并使用:
- OC 项目:
objc
#import <YYToolKit/YYToolKit.h> // 使用 NSString *str = @" test string "; NSString *trimmedStr = [YYStringTool trimWhitespace:str]; - Swift 项目:
swift
import YYToolKit // 使用 let str = " test string " let trimmedStr = YYStringTool.trimWhitespace(str)
- OC 项目:
方式 2:CocoaPods 集成(推荐团队协作)
- 为框架编写
podspec文件(如YYToolKit.podspec):rubyPod::Spec.new do |s|s.name = "YYToolKit"s.version = "1.0.0"s.summary = "iOS字符串/数据处理工具库"s.homepage = "https://github.com/xxx/YYToolKit"s.license = { :type => "MIT", :file => "LICENSE" }s.author = { "Your Name" => "your@email.com" }s.platform = :ios, "12.0"s.source = { :git => "https://github.com/xxx/YYToolKit.git", :tag => s.version }s.source_files = "YYToolKit/Classes/**/*.{h,m,swift}"s.public_header_files = "YYToolKit/YYToolKit.h" # OC专属s.swift_version = "5.0" # Swift专属 end - 发布到 CocoaPods(或本地私有库),主项目
Podfile中引入:rubypod 'YYToolKit', :git => 'https://github.com/xxx/YYToolKit.git', :tag => '1.0.0' - 执行
pod install,即可在主项目中直接导入使用。
四、高级技巧:框架的资源与混编
1. 框架中添加资源(图片、xib、plist)
- 图片资源:将图片拖入
Assets.xcassets,框架中通过[UIImage imageNamed:@"xxx" inBundle:[NSBundle bundleForClass:[YYStringTool class]] compatibleWithTraitCollection:nil](OC)或UIImage(named: "xxx", in: Bundle(for: YYStringTool.self), compatibleWith: nil)(Swift)获取; - plist 配置:添加
Config.plist到框架,通过Bundle读取:swift// Swift示例 guard let path = Bundle(for: YYStringTool.self).path(forResource: "Config", ofType: "plist"),let dict = NSDictionary(contentsOfFile: path) as? [String: Any] else {return } let apiKey = dict["API_KEY"] as? String - XIB/Storyboard:框架中创建的 XIB 需指定
Bundle加载,示例:objc// OC示例 UIViewController *vc = [[UIViewController alloc] initWithNibName:@"YYTestVC" bundle:[NSBundle bundleForClass:[YYStringTool class]]];
2. OC 与 Swift 混编框架
(1)Swift 调用 OC 代码
- 在框架中创建
YYToolKit-Bridging-Header.h桥接头文件; - 在 Build Settings 中配置「Objective-C Bridging Header」为
YYToolKit/YYToolKit-Bridging-Header.h; - 桥接头文件中引入 OC 头文件:
objc
#import "YYOCUtil.h" - Swift 中直接调用:
swift
let result = YYOCUtil.calculate(10, 20)
(2)OC 调用 Swift 代码
- Swift 代码中用
public修饰需要暴露的类 / 方法; - OC 中引入框架自动生成的头文件:
#import <YYToolKit/YYToolKit-Swift.h>; - 调用 Swift 类:
objc
YYSwiftUtil *util = [[YYSwiftUtil alloc] init]; [util doSomething];
五、框架发布与问题排查
1. 框架发布规范
- 版本号:遵循语义化版本(如 1.0.0 → 1.0.1(bug 修复)→ 1.1.0(功能新增));
- 文档:编写 README,说明集成方式、API 使用示例、最低系统版本;
- 混淆 / 加密(可选):商业 SDK 可通过代码混淆、加壳保护核心逻辑;
- 瘦身:发布前移除调试代码,用
lipo移除多余架构(如上架时移除模拟器 x86_64 架构):bash运行lipo -remove x86_64 YYToolKit.framework/YYToolKit -o YYToolKit.framework/YYToolKit
2. 常见问题排查
| 问题现象 | 排查方向 |
|---|---|
| 编译报错「Undefined symbols for architecture arm64」 | 1. 检查框架架构是否包含 arm64;2. 确认静态框架是否正确链接;3. 检查符号是否公开 |
| 运行时找不到资源 | 确认资源路径使用框架的 Bundle,而非主程序 Bundle |
| Swift 调用 OC 提示 “找不到类” | 检查桥接头文件路径配置是否正确,OC 类是否添加#import <Foundation/Foundation.h> |
| 动态框架上架被拒 | 确认动态框架已嵌入到 App Bundle 中,且未使用私有 API |
六、总结
创建 iOS 框架的核心是「明确封装边界(公共 / 私有接口)+ 规范编译配置 + 适配多场景(真机 / 模拟器、OC/Swift)」。开发阶段优先用动态框架提升调试效率,发布阶段可根据需求选择静态框架(减小 IPA 体积)或动态框架(模块化)。
框架设计的关键原则:
- 高内聚低耦合:一个框架聚焦一类功能(如网络、UI、工具类);
- 接口简洁:对外暴露最少的接口,隐藏实现细节;
- 兼容性:兼容主流 iOS 版本,避免使用私有 API;
- 可测试:为框架编写单元测试,保证核心功能稳定性。