题目
使用Combine框架实现简单字符串发布与订阅
信息
- 类型:问答
- 难度:⭐
考点
Publisher创建,Subscriber订阅,Sink操作符
快速回答
使用Just创建Publisher,通过sink实现订阅:
- 创建字符串Publisher:
let publisher = Just("Hello, Combine!") - 使用
sink订阅:publisher.sink { print($0) } - 处理完成事件:在
sink的receiveCompletion中处理结束状态
原理说明
Combine是Apple的响应式编程框架,核心是Publisher(发布者)和Subscriber(订阅者)模式:
- Publisher:数据源,遵循
Publisher协议,可发送值和完成事件 - Subscriber:通过
subscribe(_:)连接Publisher,接收数据流 - Sink:最常用的订阅操作符,提供闭包处理数据和完成事件
代码示例
import Combine
// 1. 创建Publisher
let greetingPublisher = Just("Hello, Combine!")
// 2. 使用sink订阅
let cancellable = greetingPublisher.sink(
receiveCompletion: { completion in
switch completion {
case .finished:
print("数据流完成")
case .failure(let error):
print("错误: ", error) // Just不会发送错误
}
},
receiveValue: { value in
print("收到值: ", value) // 输出: Hello, Combine!
}
)
// 3. 管理生命周期(可选)
// cancellable.cancel() // 需要时取消订阅最佳实践
- 使用
Just发布单个值,适用于简单场景 - 始终存储返回的
AnyCancellable对象,否则订阅会立即被释放 - 在
receiveCompletion中处理完成/错误状态 - 对于UI操作,在主线程接收数据:添加
.receive(on: DispatchQueue.main)
常见错误
- 忘记存储cancellable:导致订阅立即终止
// 错误:未存储返回值 Just("Hi").sink { print($0) } // 不会执行 - 混淆Publisher类型:
Just只能发送一次值,PassthroughSubject适合多次发送 - 线程问题:在后台线程更新UI
publisher .subscribe(on: DispatchQueue.global()) // 在后台处理 .receive(on: DispatchQueue.main) // 在主线程接收(正确做法) .sink { ... }
扩展知识
- Publisher类型:
Just:发送单个值后结束Future:异步返回单个值PassthroughSubject:手动发送值的Publisher
- 生命周期管理:
- 将
AnyCancellable存储在Set<AnyCancellable>中 - 使用
store(in: &cancellables)简化管理
- 将
- 操作符链式调用:
["A", "B", "C"].publisher .filter { $0 != "B" } .sink { print($0) } // 输出A,C