内容概览
前言使用 使用 比如,当你发起一个网络请求,并为这个请求创建了一个发布者以及连接了这个发布者的订阅者。 然后,这个订阅者的订阅操作触发了实际的网络请求。在某个时间点,你将第二个订阅者连接到了这个发布者。如果在连接第二个订阅者之前,网络请求已经完成,那么第二个订阅者将只会收到完成事件,收不到网络请求的响应结果。这时候,这个结果将不是你所期望。 在使用 使用 makeConnectable() 和 connect() 控制发布
/// 可连接的发布者,它提供了显式的连接、取消订阅的方式 /// /// 使用 `makeConnectable()` 来从任何一个失败类型是 `Never` 的发布者创建一个 `ConnectablePublisher` @available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) public protocol ConnectablePublisher : Publisher { /// 连接到发布者并返回一个用于取消发布的 `Cancellable` 实例 /// /// - 返回值: 一个用于取消发布的 `Cancellable` 实例 func connect() -> Cancellable } 在你显式地调用 现在,就让我们用 在两个订阅者都连接到发布者之后,调用 为了在你的 Combine 代码中使用 如下方的代码所示: class ConnectablePublisherDemo { private var cancellable1: AnyCancellable? private var cancellable2: AnyCancellable? private var connection: Cancellable? func run() { let url = URL(string: "https://")! let connectable = URLSession.shared .dataTaskPublisher(for: url) .map(\.data) .catch() { _ in Just(Data()) } .share() .makeConnectable() // 阻止发布者发布内容 cancellable1 = connectable .sink(receiveCompletion: { print("Received completion 1: \($0).") }, receiveValue: { print("Received data 1: \($0.count) bytes.") }) DispatchQueue.main.asyncAfter(deadline: .now() + 1) { self.cancellable2 = connectable.sink(receiveCompletion: { log("Received completion 2: \($0).") }, receiveValue: { log("Received data 2: \($0.count) bytes.") }) } DispatchQueue.main.asyncAfter(deadline: .now() + 2) { // 显式地启动发布。返回值需要被强引用,可用于取消发布(主动调用cancel方法或返回值被析构) self.connection = connectable.connect() } } } 请注意,在 使用 autoconnect() 操作符进行自动连接某些 对于这种情况, let cancellable = Timer.publish(every: 1, on: .main, in: .default) .autoconnect() .sink() { date in print ("Date now: \(date)") } 上面的代码示例中使用了 总结
|
|