Swift中的响应式编程(iOS/macOS):Combine和RxSwift
响应式编程是一种以异步数据流和变化传播为核心的编程范式。在Apple的iOS和macOS生态系统中,主要工具是原生框架Combine(从iOS 13/macOS 10.15开始)和第三方库RxSwift。两者都允许编写声明式、简洁且易于测试的代码,使开发者摆脱“回调地狱”和复杂的状态管理。
基本概念
- Publisher(发布者) — 数据源,可以发送值、完成信号或错误。
- Subscriber(订阅者) — 从Publisher接收数据并做出响应。
- Operator(操作符) — 用于转换数据流的函数(map, filter, combineLatest, debounce等)。
- Subject — 一种混合体,既可以接收事件,也可以发送事件(PassthroughSubject, CurrentValueSubject)。
- Scheduler(调度器) — 决定代码在哪个线程上执行。
Combine:Apple原生框架
Combine内置于Foundation中,与Publisher和Subscriber配合使用。以下是一个处理文本字段的示例:
import Combineimport UIKit
class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! @IBOutlet weak var label: UILabel! private var cancellables = Set<AnyCancellable>()
override func viewDidLoad() { super.viewDidLoad() // 从NotificationCenter创建Publisher let publisher = NotificationCenter.default .publisher(for: UITextField.textDidChangeNotification, object: textField) .compactMap { ($0.object as? UITextField)?.text } .debounce(for: .milliseconds(500), scheduler: RunLoop.main) .removeDuplicates() // 订阅 publisher .sink { [weak self] value in self?.label.text = "您输入了: \\(value)" } .store(in: &cancellables) }}该示例使用debounce延迟对输入的响应,并使用removeDuplicates忽略重复值。
RxSwift:强大的替代方案
RxSwift是ReactiveX在Swift中的移植版本。它提供了更广泛的操作符集,并支持更早版本的iOS。同样的示例使用RxSwift实现:
import RxSwiftimport RxCocoa
class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! @IBOutlet weak var label: UILabel! private let disposeBag = DisposeBag()
override func viewDidLoad() { super.viewDidLoad() textField.rx.text .orEmpty .debounce(.milliseconds(500), scheduler: MainScheduler.instance) .distinctUntilChanged() .subscribe(onNext: { [weak self] text in self?.label.text = "您输入了: \\(text)" }) .disposed(by: disposeBag) }}请注意使用了rx.text(通过RxCocoa)和distinctUntilChanged() — 相当于Combine中的removeDuplicates。
关键操作符
map/compactMap— 转换值。filter— 仅通过满足条件的值。combineLatest— 合并多个流中的最新值。zip— 成对合并多个流中的元素。flatMap— 将一个流转换为另一个流(常用于网络请求)。catch/retry— 错误处理。