我想与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)
}))
谢谢。
答案 0 :(得分:5)
.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
,这打破了保持生存的保留周期,因此{{ 1}}和Sink
也被销毁,没有内存泄漏。