RxSwift 是 Swift 的响应式编程库,实现了 Observable 模式。根据 ReactiveX, 2025 的数据,它是 Apple 生态系统中最受欢迎的 Reactive Extensions 实现。Observable 作为事件源,Observer 订阅以接收事件。
要点
RxSwift 是 Swift 语言的响应式编程库,从 Reactive Extensions (Rx) 移植而来。它允许通过 Observable Sequence(随时间可用的数据序列)来描述异步和事件驱动的程序。iOS 开发者使用 RxSwift 来处理网络请求、UI 事件和流数据,无需嵌套回调。
RxSwift 的基础由两个关键协议组成:ObservableType — 事件源,可以发出三种类型的信号:.next(value)、.error(error) 和 .completed。Observer 通过 subscribe 方法订阅 Observable 并接收这些事件。这种模型称为 Reactive Streams,保证在正确订阅的情况下不会丢失任何事件。
RxSwift 提供 300 多个操作符用于处理流:map 转换每个事件,filter 仅通过符合条件的,flatMap 将嵌套的 Observable 展开为单个流。操作符组合成链,创建无副作用的声明式数据处理管道。
除基本 Observable 外,RxSwift 还提供专门的包装类型。Single 发出恰好一个值或错误 — 非常适合 HTTP 请求。Completable 无值地以成功或错误结束 — 用于写入操作。Maybe 结合了两种场景:可以有值、无值或错误结束。这些 Traits 简化了语义,使代码自我文档化。
RxSwift 中的响应式编程基于 Observer 模式。ObservableSequence 是标准库中 Sequence 的类比,但具有对元素的异步访问。事件流通过操作符链传递,每个操作符返回新的 ObservableSequence,不改变原始序列。
RxSwift 中的操作符是纯函数,接受一个 ObservableSequence 并返回一个新的。例如,map 通过对每个元素应用转换来创建新序列。通过组合操作符,开发者构建管道,数据在其中通过所有处理阶段,无需中间变量。
Schedulers 是 RxSwift 中对执行线程的抽象。Scheduler 确定代码在哪个线程上执行:MainScheduler — UI 线程,SerialDispatchQueueScheduler — 后台队列。subscribeOn 和 observeOn 操作符指定在哪里执行工作以及在哪里处理结果。
RxSwift 包含几种基本类型,每种类型在响应式管道中解决自己的任务。Single — 发出恰好一个值或错误的 Observable,方便网络请求。Completable 无值地以成功或错误结束。Maybe 结合了 Single 和 Completable 的属性。
Subject 是一个热 Observable,同时充当 Observer。PublishSubject 仅向订阅者发出新事件,BehaviorSubject — 最后一个事件加上新事件。Relay 是 Subject 的一个变体,不发出 .error 或 .completed,保证流的连续性。BehaviorRelay 存储当前值,适合 State-driven UI。
DisposeBag 是一个 Disposable 集合,在自身释放时自动取消所有订阅。在 iOS 中,DisposeBag 通常添加到 UIViewController 或 UIView。当屏幕关闭时,DisposeBag 被清理 — 这可以防止内存泄漏和对不存在的 UI 元素的引用。
以下展示了使用 map 操作符从数据数组创建 Observable 以转换字符串的示例:
let observable = Observable.of("Swift", "RxSwift", "Reactive")
observable
.map { $0.uppercased() }
.subscribe(onNext: { value in
print("收到: \(value)")
})
.disposed(by: disposeBag)
第二个示例演示了使用 zip 组合两个网络请求 — 操作符等待两个 Observable 发出值,并将结果组合成元组:
let first = fetchUser(id: "123")
let second = fetchPosts(userId: "123")
Observable
.zip(first, second)
.observe(on: MainScheduler.instance)
.subscribe(onNext: { user, posts in
updateUI(user: user, posts: posts)
})
.disposed(by: disposeBag)
第三个示例展示了使用 BehaviorRelay 存储状态并在更改时自动更新 UI:每次 state.accept() 的更改立即传输给订阅者,这非常适合 MVVM 架构中的 State 模式。
let state = BehaviorRelay(value: "idle")
state
.subscribe(onNext: { status in
print("状态: \(status)")
})
.disposed(by: disposeBag)
state.accept("loading") // 将输出: 状态: loading
RxSwift 与传统异步方法(Delegation、NotificationCenter、Callback)在声明性和可组合性方面不同。与 Combine 不同,RxSwift 支持 iOS 9+ 并有更多操作符。然而,Combine 在语言级别与 Foundation 和 SwiftUI 集成,这使其在新的 Apple 项目中具有优势。
RxSwift 相对于 GCD(Grand Central Dispatch)的主要优势 — 能够在抽象级别组合和转换数据流,而不是手动管理队列。同时,RxSwift 需要学习响应式方法的概念,这提高了团队的入门门槛。
在实践中,RxSwift 用于大型项目,其中响应式链将 UI 事件、业务逻辑和网络交互连接在单个管道中。例如,在交易应用中,报价流通过 RxSwift 处理:tick 从 WebSocket 到达,经过过滤,按时间框架分组,并实时显示在图表上。这样的场景很难通过 Delegation 或 NotificationCenter 在不损失可读性的情况下实现。
RxSwift 的替代方案包括 Combine(iOS 13+)、Swift Concurrency 的 AsyncSequence(iOS 15+),以及不绑定 Apple 平台的 ReactiveSwift 库。选择取决于最低支持的 iOS 版本和开发者的经验。对于 iOS 15+ 的新项目,团队通常选择 AsyncSequence — 不需要安装库,并使用 Swift 语言的本地构造。
RxSwift 的架构模式通常遵循 MVVM 或 Clean Architecture。ViewModel 以 Observable 链的形式包含所有业务逻辑,View 订阅转换后的数据。Input-Output 模式将输入事件(点击、文本输入)和输出状态(按钮文本、加载器可见性)分开。这种方法简化了测试:ViewModel 通过虚拟 Scheduler 无需 UI 即可测试。
RxSwift 既适用于几个屏幕的小项目,也适用于具有数十个模块的大型企业应用。在大型项目中,响应式链贯穿整个架构:从通过 RxProperty 观察 UserDefaults 到通过 Moya(Alamofire 上的 RxSwift 包装器)进行网络请求。每个模块都是隔离的,并通过响应式接口进行通信,这简化了实现替换而无需更改订阅者。使用正确的架构,RxSwift 与传统方法相比减少了代码量,因为不需要为 KVO、Target-Action 或 NotificationCenter 编写样板代码。
RxSwift 在带有 RxDataSources 的项目中得到积极使用 — 这是一个用于响应式操作 UITableView 和 UICollectionView 的库。RxDataSources 自动计算新旧单元格集之间的差异,并应用动画更改。这使开发者免于手动使用 beginUpdates/endUpdates,并消除了数据不一致时的崩溃。
为了调试 RxSwift 链,存在 debug() 操作符 — 它记录所有事件:subscribe、next、error、completed、dispose。这是开发复杂响应式管道时不可或缺的工具。debug(String) 接受一个标识符,显示在日志中。对于内存分析,RxSwift.Resources.total 显示应用程序中活动 Observable 和 Disposable 的总数 — 有助于在 DisposeBag 未清理或 retain cycle 保持订阅时检测泄漏。额外的操作符 takeUntil(self.rx.deallocated) 在对象释放时自动取消订阅 — 这是防止泄漏的另一层保护。
在编写 RxSwift 代码时,遵循 每个订阅一个 Observable 的原则很重要:每个 ViewController 不应创建一个 Observable 的多个订阅 — 这降低了竞争条件的风险。Observable 的备忘录化使用 share() 操作符,它将冷 Observable 转换为具有大小为 1 的 replay 缓冲区的热 Observable。处理共享资源时,使用 connect() 来管理发射的开始 — 这保证所有订阅者在第一个事件之前连接。
RxSwift 代码的测试通过 TestScheduler 执行 — 一个允许管理时间的虚拟 Scheduler。testScheduler.createHotObservable(values) 创建一个具有按虚拟时间预定义事件序列的 Observable。testScheduler.start() 启动处理。TestScheduler 允许检查事件发生的顺序和虚拟时间戳,无需实际延迟,从而使测试快速且确定性。
常见问题
Observable 是冷源:在订阅之前不发出事件。Subject 是热的:独立于订阅者发出事件,并允许通过 onNext 手动插入值。PublishSubject 仅传递新事件,BehaviorSubject — 最后一个加上新事件。
DisposeBag 存储所有 Disposable 订阅。当 DisposeBag 被释放时(例如,关闭 ViewController 时),所有存储的订阅自动取消。这保证 Observable 不会再向已销毁的 UI 对象发送事件。
如果最低 iOS 版本是 13+ 且团队了解 SwiftUI — 选择 Combine。如果项目支持 iOS 12 及以下版本或需要更大的操作符集 — RxSwift。Combine 提供与 Foundation(URLSession、Timer、NotificationCenter)更好的集成。
Schedulers 抽象了执行线程。subscribeOn 指示在哪个 Scheduler 上执行订阅(通常是后台)。observeOn 确定在哪个 Scheduler 上接收事件(更常见的是 MainScheduler 用于 UI 更新)。SerialDispatchQueueScheduler 通过 GCD 工作。
是的,RxSwift 可以通过 ObservableObject 与 SwiftUI 集成。将 BehaviorRelay 用作 @Published 属性:订阅 Relay 将更改传输到 Combine,SwiftUI 通过 @ObservedObject 重新绘制 View。这是从 UIKit 迁移到 SwiftUI 的流行模式。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。