use*_*557 3 swift swiftui combine
我想用 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)
})
Run Code Online (Sandbox Code Playgroud)
所以我将.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)
}))
Run Code Online (Sandbox Code Playgroud)
提前致谢。
该.sink运营商做了三两件事:
Subscribers.Sink使用您传递给它的两个闭包创建一个。subscribe上游Publisher,传递Sink它创建的。AnyCancellable,当销毁时,取消Sink. 它返回对 this 的引用AnyCancellable。AnyCancellable是一个引用计数对象。当对 的最后一个引用AnyCancellable被销毁时,它AnyCancellable本身也被销毁。那时,它会调用自己的cancel方法。
在你的第一个例子,你是不是保存AnyCancellable的返回.sink。所以 Swift 会立即销毁它,这意味着它会立即取消订阅。一秒钟后,您的asyncAfter闭包调用promise,但订阅已被取消,因此receiveValue不会调用您的闭包。
在您的第二个示例中,由于您正在创建Subscribers.Sink对象并将其传递给subscribe自己,AnyCancellable因此创建了no来包装Sink. 所以没有什么会自动破坏订阅。一秒钟后,asyncAfter闭包调用promise。由于订阅没有被销毁,它仍然存在,所以你的receiveValue闭包被调用,然后你的receiveCompletion闭包被调用。
所以这实际上是一个非常有趣的Subscribers.Sink替代.sink操作符的用法。使用.sink,您必须保存返回的AnyCancellable,否则订阅将立即取消。但是通过Subscribers.Sink直接使用,您创建的订阅一直持续到完成,您无需保存任何内容。当订阅完成时(使用.finished或.failure),Sink丢弃Subscription,这打破了保持它活着的保留周期,因此Sink和Subscription也被销毁,不会留下内存泄漏。
| 归档时间: |
|
| 查看次数: |
772 次 |
| 最近记录: |