本文首发于 Ficow Shen’s Blog,原文地址: Combine 框架,从0到1 —— 5.Combine 常用操作符。
内容概览
- 前言
- breakpoint
- handleEvents
- map
- flatMap
- eraseToAnyPublisher
- merge
- combineLatest
- zip
- setFailureType
- switchToLatest
- 总结
前言
正所谓,工欲善其事,必先利其器。在开始使用 Combine
进行响应式编程之前,建议您先了解 Combine
为您提供的各种发布者(Publishers)、操作符(Operators)、订阅者(Subscribers)。
Combine 操作符(Operators) 其实是发布者,这些操作符发布者的值由上游发布者提供。操作符封装了很多常用的响应式编程算法,有一些可以帮助我们更轻松地进行调试,而另一些可以帮助我们更轻松地通过结合多个操作符来实现业务逻辑,本文将主要介绍这两大类操作符。
后续示例代码中出现的 cancellables
均由 CommonOperatorsDemo
实例提供:
final class CommonOperatorsDemo {
private var cancellables = Set<AnyCancellable>()
}
官网文档:https://developer.apple.com/documentation/combine/publishers/print
print
操作符主要用于打印所有发布的事件,您可以选择为输出的内容添加前缀。
print
会在接收到以下事件时打印消息:
- subscription,订阅事件
- value,接收到值元素
- normal completion,正常的完成事件
- failure,失败事件
- cancellation,取消订阅事件
示例代码:
func printDemo() {
[1, 2].publisher
.print("_")
.sink {
_ in }
.store(in: &cancellables)
}
输出内容:
_: receive subscription: ([1, 2])
_: request unlimited
_: receive value: (1)
_: receive value: (2)
_: receive finished
breakpoint
官网文档:https://developer.apple.com/documentation/combine/publishers/breakpoint
breakpoint
操作符可以发送调试信号来让调试器暂停进程的运行,只要在给定的闭包中返回 true
即可。
示例代码:
func breakpointDemo() {
[1, 2].publisher
.breakpoint(receiveSubscription: {
subscription in
return false // 返回 true 以抛出 SIGTRAP 中断信号,调试器会被调起
}, receiveOutput: {
value in
return false // 返回 true 以抛出 SIGTRAP 中断信号,调试器会被调起
}, receiveCompletion: {
completion in
return false // 返回 true 以抛出 SIGTRAP 中断信号,调试器会被调起
})
.sink(receiveValue: {
_ in
})
.store(in: &cancellables)
}
您可能会好奇,为什么需要用这个操作符来实现断点,为何不直接打断点呢?
从上面的示例代码中,我们可以看出,通过使用 breakpoint
操作符,我们可以很容易地在订阅操作、输出、完成发生时启用断点。
如果这时候想直接在代码上打断点,我们就要重写 sink
部分的代码,而且无法轻易地为订阅操作启用断点。
handleEvents
官网文档:https://developer.apple.com/documentation/combine/publishers/handleevents
handleEvents
操作符可以在发布事件发生时执行指定的闭包。
示例代码:
func handleEventsDemo() {
[1, 2].publisher
.handleEvents(receiveSubscription: {
subscription in
// 订阅事件
}, receiveOutput: {
value in
// 值事件
}, receiveCompletion: {
completion in
// 完成事件
}, receiveCancel: {
// 取消事件
}, receiveRequest: {
demand in
// 请求需求的事件
})
.sink(receiveValue: {
_ in
})
.store(in: &cancellables)
}
handleEvents
接受的闭包都是可选类型的,所以我们可以只需要对感兴趣的事件进行处理即可,不必为所有参数传入一个闭包。
map
官网文档:https://developer.apple.com/documentation/combine/publishers/map
map
操作符会执行给定的闭包,将上游发布的内容进行转换,然后再发送给下游订阅者。和 Swift 标准库中的 map
函数类似。
示例代码:
func mapDemo() {
[1, 2].p