我想用 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
,这打破了保持它活着的保留周期,因此 Sink
和 Subscription
也被销毁,不会留下内存泄漏。
关于swift - .sink 和 Subscribers.Sink 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61216852/