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 次 |
最近记录: |