RxSwift — 什么是它,功能和响应式编程

作者: IT Sectr 发布日期: 2026-05-03 阅读时间: 10 分钟

RxSwift 是一个用于 iOS 的响应式编程库,实现了 Observable 模式和功能性运算符来处理异步数据流。它将 ReactiveX (Rx) 的概念移植到 Swift 语言,提供统一的 API 来处理来自 UI、网络请求、数据库和定时器的事件。据 ReactiveX, 2025,该库在 GitHub 上被 60,000 多个项目使用,并且在原生 Combine 出现之前一直是 Swift 响应式编程的标准。RxSwift 用统一的事件处理链替代了代理、闭包和通知。

主要要点

  • RxSwift — ReactiveX 在 Swift 上的实现,基于 Observable 模式和运算符链
  • Observable — 异步事件的源,可以成功、出错或无限终止
  • Subject — Observable 和 Observer 的混合体,允许手动向流中发送事件
  • Schedulers 管理订阅、观察和事件处理在哪个线程上执行
  • 运算符 map、flatMap、filter、combineLatest 无竞态竞争地转换和组合流

什么是 RxSwift?

RxSwift 是 ReactiveX (Rx) 库的 Swift 移植版,该库由 Microsoft 于 2012 年为 .NET 创建。Rx 的主要思想是将任何异步数据源表示为可应用功能性运算符的 Observable 序列。在 iOS 开发中,RxSwift 用于将 UI 事件(按钮点击、文本输入、手势)与应用程序逻辑连接,无需显式的代理和 target-action。

该库由三个模块组成:RxSwift(核心 — Observable、Operator、Scheduler)、RxCocoa(与 UIKit 集成 — 针对 UIButton、UITextField、UITableView 的 rx 扩展)和 RxRelay(没有终端事件的 Subject)。这种划分允许在服务端 Swift 和测试中使用核心,仅为 iOS 应用程序连接 UI 层。

Stack Overflow, 2025 调查,RxSwift 位列 iOS 最常用的第三方库前五名。其受欢迎的主要原因是统一处理所有异步模式:通过 URLSession 进行网络请求、通过 UIViewPropertyAnimator 进行动画、通过 NotificationCenter 进行通知以及通过 DelegateProxy 进行代理 — 所有这些都化为具有可预测生命周期的 Observable。

响应式编程的哲学

响应式编程 是一种范式,程序对数据变化做出响应,而不是轮询。与其编写“获取数据 → 处理 → 更新 UI”,开发者描述一个转换链:“当数据改变时,应用过滤器,然后 map,然后更新 UI”。RxSwift 通过具有惰性执行的 Observable 链实现这种范式 — 在出现订阅者之前,什么也不会发生。

RxSwift 的关键组件:Observable、Subject、Disposable

Observable 是 RxSwift 的基础类型,表示时间上的事件序列。Observable 可以发送三种类型的事件:next(新值)、error(错误,终止流)和 completed(成功完成)。存在有限 Observable(发送所有值后终止)和无限 Observable(例如 UI 事件 — 从不终止)。

Observable 的生命周期

生命周期 Observable 包括三个阶段:创建(create、just、from)、转换(map、filter、flatMap 运算符)和订阅(subscribe)。没有订阅,Observable 不执行任何操作 — 它是一个惰性序列。订阅后,Observable 开始向订阅者发送事件,直到它终止或订阅者通过 Disposable 取消订阅。

swift
import RxSwift

// 从数组创建 Observable
let numbers = Observable.from([1, 2, 3, 4, 5])

// 通过运算符进行转换
let squared = numbers
    .filter { $0 % 2 == 0 }
    .map { $0 * $0 }

// 带事件处理的订阅
let disposable = squared
    .subscribe(onNext: { print($0) },
               onError: { print("Error: \($0)") },
               onCompleted: { print("Done") })

Subject 是一种同时是 Observable(可以订阅)和 Observer(可以发送事件)的类型。RxSwift 提供四种 Subject:PublishSubject(仅新事件)、BehaviorSubject(带初始值)、ReplaySubject(缓存最后 N 个事件)和 AsyncSubject(仅在终止前最后一个值)。Subject 方便将强制性代码(闭包、代理)集成到响应式链中。

Disposable 是取消订阅的 token。当订阅者不再想接收事件时,调用 disposable.dispose()。在实践中使用 DisposeBag:一个 Disposable 的集合,在所有者释放时(例如 UIViewController)自动取消所有订阅。这防止了手动管理订阅时不可避免的内存泄漏。

Subject 类型初始值向订阅者重复用途
PublishSubject仅新事件UI 事件、稀有通知
BehaviorSubject最后 + 新状态、数据流
ReplaySubject缓冲 N + 新历史缓存
AsyncSubject仅最后计算任务
PublishRelay仅新无 error/completed

流的转换和过滤运算符

运算符 RxSwift 是接收一个 Observable 并返回另一个 Observable 的函数,转换数据流。通过组合运算符,开发者构建无中间变量和竞态竞争的当前式处理链。所有运算符都是惰性的:链在描述时构建,在订阅时执行。

转换运算符 改变流中的每个事件。map 对每个元素应用函数,flatMap 将每个元素的 Observable 展开为单个平滑流,scan 累积中间结果(类似于 reduce,但每步都发射)。buffer 按时间或数量分组元素,window 按窗口将流分为嵌套的 Observable。

swift
// 运算符链示例:带 debounce 的搜索
searchTextField.rx.text
    .orEmpty
    .debounce(.milliseconds(300), scheduler: MainScheduler.instance)
    .distinctUntilChanged()
    .flatMapLatest { query -> Observable<[String]> in
        return apiService.search(query)
    }
    .bind(to: tableView.rx.items(cellIdentifier: "Cell")) { _, item, cell in
        cell.textLabel?.text = item
    }
    .disposed(by: disposeBag)

过滤运算符 只允许满足条件的事件通过。filter 按谓词分离,distinctUntilChanged 只允许与前一个不同的值通过,take 和 takeWhile 限制事件数量。skipskipWhile 跳过前 N 个事件或直到条件满足。错误处理使用 catchError(捕获和替换)和 retry(出错时重复序列)。

组合运算符 将多个 Observable 合并为一个。combineLatest 将来自多个流的最后值组合为元组,zip 按索引将元素成对组合,merge 按事件到达顺序合并多个流。withLatestFrom 将来自主流的事件与另一个流的最后值组合 — 方便用于带当前状态的 UI 事件。

类别运算符功能
转换map通过函数转换每个值
转换flatMap将嵌套 Observable 展开为平滑流
过滤filter按谓词允许值通过
过滤distinctUntilChanged仅允许已更改的值通过
组合combineLatest组合来自 2+ 流的最后值
组合zip按索引将元素成对组合
管理debounce延迟事件直到流中暂停
管理take获取前 N 个事件并终止流

Schedulers 和执行线程管理

Scheduler 在 RxSwift 中是对执行线程(或队列)的抽象。Scheduler 确定事件创建、转换和订阅在哪个线程上执行。与 GCD 不同,开发者显式指定 DispatchQueue,RxSwift 使用两个参数:subscribeOn(Observable 在哪个线程上执行)和 observeOn(订阅者在哪个线程上被调用)。

MainScheduler 和 BackgroundScheduler

MainScheduler 在主线程上执行代码 — 更新 UIKit 必须(所有 UI 变更必须在 main thread 上进行)。SerialDispatchQueueScheduler 包装序列 GCD 队列,ConcurrentDispatchQueueScheduler 包装并行队列。后台任务使用带 qos: .background 或 .utility 的 ConcurrentDispatchQueueScheduler。

swift
// 典型模式:后台工作 + UI 在 main 上
apiService.fetchData()
    .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
    .observeOn(MainScheduler.instance)
    .subscribe(onNext: { data in
        self.tableView.reloadData()
        self.loadingIndicator.stopAnimating()
    })
    .disposed(by: disposeBag)

正确使用 Scheduler 防止在网络请求和重型计算时阻塞 UI。subscribeOn 影响整个 upstream(所有运算符在 observeOn 之前在指定的调度器上执行)。observeOn 切换 downstream — observeOn 之后的所有运算符在指定的调度器上执行。链中可以有多个 observeOn 用于在不同转换阶段切换线程。

RxSwift 在 iOS 中的实践应用

RxSwift 在 iOS 项目中最常用于通过响应式链将 UI 与数据连接。RxCocoa 为所有标准 UIKit 组件提供 rx 扩展:UIButton 的 rx.tap、UITextField 的 rx.text、UIPickerView 的 rx.selectedRow。这允许放弃 @IBAction 和代理,用当前式订阅替代它们。

RxSwift 与 MVVM 结合

MVVM(Model-View-ViewModel)是一种架构模式,ViewModel 管理状态和业务逻辑,View 订阅 ViewModel 的响应式属性。RxSwift 完美适合 MVVM:ViewModel 发布 Observable 或 Driver 供数据,View 通过 bind 订阅它们。ViewModel 不引用 View — 它返回 View 消费的 Observable。

swift
class LoginViewModel {
    let email = BehaviorRelay<String>(value: "")
    let password = BehaviorRelay<String>(value: "")

    var isFormValid: Observable<Bool> {
        return Observable
            .combineLatest(email, password) {
                !$0.isEmpty && $0.contains("@") && $1.count >= 6
            }
    }
}

// 在 ViewController 中:
viewModel.isFormValid
    .bind(to: loginButton.rx.isEnabled)
    .disposed(by: disposeBag)

网络请求是 RxSwift 第二常见的应用领域。URLSession.rx.response 将 HTTP 请求包装为 Observable,成功时返回 (response, data),失败时返回 error。与 Codable 和 map 运算符组合后,得到精简的响应式 API 层:每个方法中无需回调和错误处理的 Observable<MyModel>。网络错误时,retry(3) 运算符会以指数衰减延迟自动重复请求三次。

RxSwift 与 Combine 对比

Combine 是 Apple 的原生框架,在 iOS 13 中引入。它解决与 RxSwift 相同的任务:通过 Publisher、Subscriber 和运算符处理异步事件。但 Combine 有关键差异:通过 Failure 类型实现严格错误类型化、内置支持 Swift Concurrency(async/await)以及通过 @Published 和 ObservableObject 与 SwiftUI 集成。

RxSwift 在向后兼容性方面胂出 — 支持 iOS 8+,而 Combine 需要 iOS 13+。RxSwift 拥有更丰富的第三方扩展生态系(RxDataSources、RxGesture、RxAnimated)和详细的运算符文档。对于支持旧版 iOS 的项目,RxSwift 仍是唯一选择。

对于 iOS 13+ 的新项目,Apple 推荐 Combine。它与 SwiftUI 紧密集成,具有更小的二进制文件大小和官方支持。但将现有 RxSwift 代码迁移到 Combine 需要重写所有 Observable → Publisher,而 RxCocoa 生态系在 Combine 中没有完整等效物 — UIKit 没有针对所有 UI 组件的原生 Publisher。

特性RxSwiftCombine
最低 iOSiOS 8+iOS 13+
错误类型Error(任意)Generic Failure
UI 扩展RxCocoa(UIKit, AppKit)@Published(SwiftUI)
运算符400+ 运算符~100 运算符
Swift Concurrency通过桥接原生支持
状态第三方Apple 官方

常见问题

RxSwift 中 Observable 和 Subject 有什么区别?

Observable 是带惰性执行的事件源。Subject 同时是 Observable 和 Observer — 您可以订阅它并手动向它发送新事件。Subject 方便将强制性代码集成到响应式链中。

什么时候使用 RxSwift 而不是 Combine?

RxSwift 在需要支持 iOS 11-12、有现有 RxSwift 代码基础或需要丰富的运算符生态系时(Combine 中的 ~100 与 400+)被选择。对于 iOS 13+ 的新项目,更倾向于 Combine。

什么是 DisposeBag,它有什么用?

DisposeBag 是 Disposable token 的集合,在所有者释放时自动取消所有订阅。没有 DisposeBag,订阅会对闭包创建强引用,导致 UIViewController 被销毁时内存泄漏。

如何在 RxSwift 中处理错误?

使用 catchError 将错误替换为默认值,retry 重新执行 Observable,materialize 将错误转换为事件。在 UI 层中,Driver 和 Signal 不传递错误 — 它们在内部处理。

RxCocoa 中 Driver 和 Observable 有什么区别?

Driver 是一种特殊的 Observable 类型,保证在 MainScheduler 上执行、无错误和资源共享。Driver 保证 UI 更新在主线程上进行。Observable 不提供这样的保证 — 需要 observeOn。

总结

  • RxSwift — iOS 的响应式编程库,实现了 Observable 模式和 400+ 转换运算符
  • Observable、Subject、Disposable — 构成所有响应式链基础的三个基本类型
  • 运算符 map、flatMap、filter、combineLatest、debounce 允许无竞态竞争地构建当前式链
  • Schedulers(subscribeOn / observeOn)管理执行线程,防止 UI 阻塞
  • RxCocoa 为 UIKit 提供 rx 扩展,用响应式订阅替代代理和 target-action
  • Combine — Apple 针对 iOS 13+ 的原生替代方案,但 RxSwift 对于旧版本仍然有效

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读