> 技术文档 > iOS组件化详解

iOS组件化详解


一、为什么要做组件化开发?

在 iOS 项目迭代过程中,随着业务复杂度提升、团队规模扩大,传统单体架构会逐渐暴露以下问题:

  • 代码耦合严重:模块间直接依赖(如 #import \"XXViewController.h\"),改一处动全身,维护成本高;
  • 团队协作低效:多人开发同一仓库易冲突,代码合并成本高;
  • 编译速度慢:单工程代码量过大,每次编译需全量处理,耗时久;
  • 复用性差:功能模块无法单独抽离复用(如登录模块在多 APP 中重复开发);
  • 测试成本高:单模块修改需全量回归测试,影响迭代效率。

组件化的核心目标是 解耦 :将项目拆分为独立、可复用的组件,通过 “中间件” 实现组件间通信,解决上述问题。

二、iOS 组件化如何分层?

组件化架构通常分为 5 层(自底向上),每层职责清晰、依赖单向(上层依赖下层,禁止反向依赖):

层级 职责 示例组件 基础层 提供全局通用能力,不依赖任何上层模块 网络(AFNetworking、Alamofire)、存储(FMDB)、工具类(Category)、基础 UI 组件(与业务无关的) 业务基础层 封装跨业务的通用能力,依赖基础层,不依赖具体业务 登录、支付、用户信息管理、埋点统计 业务组件层 拆分独立业务模块(按功能 / 业务线),依赖基础层和业务基础层,内部高内聚 首页、购物车、订单、个人中心 中间件层 负责组件间通信(路由跳转、方法调用),解耦组件依赖 CTMediator、URLNavigator、ARouter 壳工程 整合所有组件,负责配置环境、启动页、根控制器设置,无业务逻辑 Main Project(仅包含配置文件和组件注册)
三、CTMediator 的 OC 与 Swift 实践(组件间通信)

CTMediator 是基于 “Target-Action” 模式的组件化中间件,通过运行时(OC)或桥接(Swift)实现组件间 “无依赖调用”。其核心原理:调用方通过中间件(CTMediator)发送 “指令”,中间件找到目标组件的 “Target” 类,执行对应的 “Action” 方法

3.1. OC 实践代码

假设场景:“订单组件” 调用 “支付组件” 的支付功能。

(1)中间件 CTMediator(基础类,全局唯一)

objective-c

// CTMediator.h#import @interface CTMediator : NSObject+ (instancetype)sharedInstance;// 支付组件调用方法(中间件声明)- (void)payWithOrderId:(NSString *)orderId callback:(void(^)(BOOL success))callback;@end// CTMediator.m#import \"CTMediator.h\"#import @implementation CTMediator+ (instancetype)sharedInstance { static CTMediator *instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [CTMediator new]; }); return instance;}// 调用支付组件的支付方法(通过Target-Action调用)- (void)payWithOrderId:(NSString *)orderId callback:(void(^)(BOOL success))callback { // Target_Pay:支付组件的Target类(约定命名:Target_+组件名) // action_payWithOrderId:callback::支付组件的Action方法(约定命名:action_+方法名) Class targetClass = NSClassFromString(@\"Target_Pay\"); id target = [[targetClass alloc] init]; if ([target respondsToSelector:@selector(action_payWithOrderId:callback:)]) { [target performSelector:@selector(action_payWithOrderId:callback:) withObject:orderId withObject:callback]; }}@end
(2)支付组件(业务组件层)的实现(Target-Action)

objective-c

// Target_Pay.h(仅组件内部可见,不对外暴露)#import @interface Target_Pay : NSObject// 支付Action(参数与中间件声明一致)- (void)action_payWithOrderId:(NSString *)orderId callback:(void(^)(BOOL success))callback;@end// Target_Pay.m#import \"Target_Pay.h\"#import \"PayService.h\" // 组件内部的支付逻辑@implementation Target_Pay- (void)action_payWithOrderId:(NSString *)orderId callback:(void(^)(BOOL success))callback { // 调用组件内部的支付逻辑 [[PayService shared] pay:orderId completion:^(BOOL success) { if (callback) callback(success); }];}@end
(3)调用方(如订单组件)使用

objective-c

// 订单组件中调用支付,无需#import \"PayService.h\"或\"Target_Pay.h\"#import \"CTMediator.h\"// 点击支付按钮- (void)onPayClick { NSString *orderId = @\"ORDER_123\"; [[CTMediator sharedInstance] payWithOrderId:orderId callback:^(BOOL success) { if (success) { NSLog(@\"支付成功\"); } else { NSLog(@\"支付失败\"); } }];}
3.2. Swift 实践代码(需兼容 OC 的 CTMediator)

Swift 组件需通过@objc暴露给 OC 中间件,核心是 “Swift 协议 + Target-Action”:

(1)中间件扩展(Swift 中调用 CTMediator)
// CTMediator+SwiftExtension.swiftimport UIKitextension CTMediator { // Swift中声明支付调用方法 func pay(with orderId: String, callback: @escaping (Bool) -> Void) { // 调用OC的Target-Action(注意参数转换) self.performSelector(inBackground: NSSelectorFromString(\"payWithOrderId:callback:\"), with: orderId, with: callback) }}
(2)Swift 支付组件的 Target 实现
// Target_Pay.swift(需@objc暴露给OC)@objc(Target_Pay) // 必须指定OC类名,否则CTMediator找不到class Target_Pay: NSObject { // Action方法需@objc,参数匹配 @objc func action_payWithOrderId(_ orderId: String, callback: @escaping (Bool) -> Void) { // 调用Swift支付逻辑 PayService.shared.pay(orderId: orderId) { success in callback(success) } }}// 支付逻辑(组件内部)class PayService { static let shared = PayService() func pay(orderId: String, completion: @escaping (Bool) -> Void) { // 模拟支付请求 DispatchQueue.global().asyncAfter(deadline: .now() + 1) { completion(true) } }}
(3)Swift 调用方(如订单组件)
// 订单组件中调用class OrderViewController: UIViewController { func onPayClick() { let orderId = \"ORDER_456\" CTMediator.sharedInstance().pay(with: orderId) { success in print(\"支付结果:\\(success)\") } }}
四、组件化与工程化、插件化的区别和优势
概念 核心目标 技术手段 优势 适用场景 组件化 拆分模块,解决代码耦合,提升协作效率 静态拆分模块(编译期整合),通过中间件通信(CTMediator) 解耦彻底、编译速度快、团队协作高效、模块可复用 大型 APP、多团队协作、业务稳定 工程化 规范开发流程(构建、测试、部署等),提升效率 自动化工具(Jenkins、Fastlane)、代码规范(ESLint)、CI/CD 流程 减少人为操作、标准化流程、降低出错率 所有项目(基础保障) 插件化 动态加载模块(运行时),解决包体积和动态更新问题 动态库(.framework)、反射加载、沙盒隔离(如微信小程序) 按需加载、减小包体积、支持动态更新(无需发版) 模块频繁更新、包体积敏感场景

组件化的独特优势

  • 相比工程化:工程化是 “流程规范”,组件化是 “架构设计”,前者为后者提供落地保障;
  • 相比插件化:组件化是 “静态拆分”(编译期整合),兼容性更好(无动态加载风险),适合业务稳定的大型项目;插件化是 “动态加载”,适合需频繁更新的场景,但实现复杂且受 iOS 审核限制(动态库可能被拒)。
总结

组件化是大型 iOS 项目解决耦合、提升协作效率的核心方案,通过分层设计和 CTMediator 等中间件实现模块解耦;其与工程化(流程规范)、插件化(动态加载)定位不同,需根据项目规模和业务需求选择。