至此,在《Combine: Asynchronous Programming with Swift》书中的操作符讲解已经结束了,但其实还有些操作符没有被讲解到。我们会在此一一列出。
Encoding & Decoding
encode(encoder:)
使用指定的编码器对来自上游的输出进行编码。 使用 encode(encoder:) 和 JSONEncoder,将 Encodable 结构编码为可用于生成 JSON 字符串的数据。
注意:如果您尝试将可选类型传递给 encode 运算符。这会导致编译器出错。
我们看下Apple官方文档的例子:
struct Article: Codable {
let title: String
let author: String
let pubDate: Date
}
let dataProvider = PassthroughSubject<Article, Never>()
let cancellable = dataProvider
.encode(encoder: JSONEncoder())
.sink(receiveCompletion: { print ("Completion: \($0)") },
receiveValue: { data in
guard let stringRepresentation = String(data: data, encoding: .utf8) else { return }
print("Data received \(data) string representation: \(stringRepresentation)")
})
dataProvider.send(Article(title: "My First Article", author: "Gita Kumar", pubDate: Date()))
运行playground,得到结果:
Data received 79 bytes string representation: {"title":"My First Article","author":"Gita Kumar","pubDate":656324569.12053096}
在上面代码中,encode(encoder:) 运算符将符合Codable
协议的 Article 结构,转为了 JSON 字符串。
我们可以尝试屏蔽掉encode
这行,并将sink闭包内容改为:
.sink(receiveCompletion: { print ("Completion: \($0)") },
receiveValue: { print($0) })
再运行playground,得到结果:
Article(title: "My First Article", author: "Gita Kumar", pubDate: 2021-10-19 08:25:41 +0000)
可以比较两次打印的内容,能更清晰的看出encode
生成的是JSON类型的数据。
decode(type:decoder:)
使用指定的解码器解码来自上游的输出。
将 decode(type:decoder:) 与 JSONDecoder一起使用可解析JSON类型数据,并解析为指定的数据结构。
我们将encode的代码修改下,替换encode为decode:
struct Article: Codable {
let title: String
let author: String
let pubDate: Date
}
let dataProvider = PassthroughSubject<Data, Never>()
var cancellable = dataProvider
.decode(type: Article.self, decoder: JSONDecoder())
.sink(receiveCompletion: { print ("Completion: \($0)")},
receiveValue: { print ("value: \($0)") })
dataProvider.send(Data("{\"pubDate\":1574273638.575666, \"title\" : \"My First Article\", \"author\" : \"Gita Kumar\" }".utf8))
运行playground,得到结果:
value: Article(title: "My First Article", author: "Gita Kumar", pubDate: 2050-11-20 18:13:58 +0000)
在decode中,将解析后的类型,设置为Article
,(代码中用Article.self表示)。
用PassthroughSubject发送一个JSON数据
{"pubDate":1574273638.575666, "title" : "My First Article", "author" : "Gita Kumar" }
最后,经过decode,我们得到了Article的数据。
Debugging
breakpoint
breakpoint
提供一个闭包,当闭包需要停止调试器中的进程时,发出一个调试器信号。
breakpoint的函数声明为:
func breakpoint(receiveSubscription: ((Subscription) -> Bool)? = nil, receiveOutput: ((Self.Output) -> Bool)? = nil, receiveCompletion: ((Subscribers.Completion<Self.Failure>) -> Bool)? = nil) -> Publishers.Breakpoint<Self>
参数说明:
- receiveSubscription 当发布者收到订阅时执行的闭包。闭包返回 true 会触发 SIGTRAP,或返回 false 以继续。
- receiveOutput 当发布者收到一个值时执行的闭包。闭包返回 true 会触发 SIGTRAP,或返回 false 以继续。
- receiveCompletion 当发布者收到completion时执行的闭包。闭包返回 true会触发 SIGTRAP,或返回 false 以继续。
我们看下Apple官方文档的代码示例:
let publisher = PassthroughSubject<String?, Never>()
var cancellable = publisher
.breakpoint(
receiveOutput: { value in return value == "DEBUGGER" }
)
.sink { print("\(String(describing: $0))" , terminator: " ") }
publisher.send("DEBUGGER")
运行playground,会发现代码报错:
error: Execution was interrupted, reason: signal SIGTRAP.
在breakpoint
的闭包中,我们返回了一个等式value == "DEBUGGER"
,当我们用PassthroughSubject发布一个“DEBUGGER”时,等式结果为true,所以触发了SIGTRAP
。