gpt4 book ai didi

swift - .sink 和 Subscribers.Sink 有什么区别?

转载 作者:行者123 更新时间:2023-12-04 00:01:12 28 4
gpt4 key购买 nike

我想用 Future 做一个异步工作。
但是下面的 .sink() 闭包 永远不会被调用。
看起来 Future 的实例在它被调用后就被释放了。

    Future<Int, Never> { promise in
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
promise(.success(1))
}
}
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
print(completion)
}, receiveValue: {
print($0)
})

所以我将 .sink() 闭包 替换为 .subscribe(Subscribers.Sink()) 如下所示。它工作正常。
但问题是我不明白为什么它工作正常。 :(
对我来说看起来一样。
这两个代码有什么区别?我什么时候可以使用 .sink() ,什么时候不能?
    Future<Int, Never> { promise in
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
promise(.success(1))
}
}
.receive(on: DispatchQueue.main)
.subscribe(Subscribers.Sink(receiveCompletion: { completion in
print(completion)
}, receiveValue: {
print($0)
}))

提前致谢。

最佳答案

.sink 操作符做三件事:

  • 它使用您传递给它的两个闭包创建一个 Subscribers.Sink
  • 它在上游 subscribe 上调用 Publisher ,传递它创建的 Sink
  • 它创建一个 AnyCancellable ,在销毁时取消 Sink 。它返回对此 AnyCancellable 的引用。
  • AnyCancellable 是一个引用计数对象。当对 AnyCancellable 的最后一个引用被销毁时, AnyCancellable 本身也被销毁。那时,它调用了自己的 cancel 方法。

    在您的第一个示例中,您没有保存 AnyCancellable 返回的 .sink 。所以 Swift 会立即销毁它,这意味着它会立即取消订阅。一秒钟后,您的 asyncAfter 闭包调用 promise ,但订阅已被取消,因此不会调用您的 receiveValue 闭包。

    在您的第二个示例中,由于您正在创建 Subscribers.Sink 对象并将其传递给 subscribe ,因此没有创建 AnyCancellable 来包装 Sink 。所以没有什么会自动破坏订阅。一秒钟后, asyncAfter 闭包调用 promise 。由于订阅没有被销毁,它仍然存在,所以你的 receiveValue 闭包被调用,然后你的 receiveCompletion 闭包被调用。

    所以这实际上是一个非常有趣的使用 Subscribers.Sink 而不是 .sink 操作符。使用 .sink ,您 必须 保存返回的 AnyCancellable ,否则订阅将立即取消。但是通过直接使用 Subscribers.Sink,您可以创建一个持续到订阅完成的订阅,您无需保存任何内容。当订阅完成时(使用 .finished.failure ), Sink 丢弃 Subscription ,这打破了保持它活着的保留周期,因此 SinkSubscription 也被销毁,不会留下内存泄漏。

    关于swift - .sink 和 Subscribers.Sink 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61216852/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com