如何解决Swift Combine Sink收到至少一个值后如何停止存储AnyCancellable?
我有一个接收器,需要在接收到第一个值后立即取消。我不在乎未来的价值,只有第一个发表。因为垃圾收集器不会存储接收器创建的AnyCancelable
,所以会删除接收器,因此必须存储它。同时,在接收器完成后,我还必须清理它,否则会发生内存泄漏。
我使用UUID→AnyCancelable映射构建了一个映射,但是我担心它比应该的要复杂得多。还有另一种方法吗? Combine推荐什么?
@Published var locationState: (location: CLLocation?,error: Error?)?
var requestLocationSinks: [String: AnyCancellable] = [:]
// 1. Generate ID to uniquely identify the current sink.
let sinkID = UUID().uuidString
// 2. Start the sink and store it in our ID → AnyCancellable dictionary.
requestLocationSinks[sinkID] = $locationState.sink { locationState in
if let locationState = locationState {
invokeCallbackWithLocationState(locationState)
}
// 3. Remove the stored AnyCancellable as soon as we received our first value!
self.requestLocationSinks.removeValue(forKey: sinkID)
}
解决方法
如果只需要保持活动状态直到接收器被调用一次,就可以创建一个临时变量
var cancellable: AnyCancellable?
cancellable = $locationState.sink { locationState in
if let locationState = locationState {
invokeCallbackWithLocationState(locationState)
}
cancellable = nil
}
这将使AnyCancellable
保留足够长的时间(因为闭包保留了引用)
如果您仅对上游的第一个元素感兴趣,则可以使用运算符.first()
或运算符.prefix(1)
。他们是平等的。使用.prefix(n)
,您可以定义传递的上游元素的数量。
myPublisher
.first()
.sink( ... )
or
myPublisher
.prefix(1 or n)
.sink( ... )
请注意,上述两个运算符会导致.finished
完成。这意味着该操作后订阅将被删除。
publisher is triggered -> receiveValue -> receiveCompletion (finished) -> subscription is deleted
如果您使用AnyCancellable
,并且想要删除您的订阅,则应该使用.cancel()
的{{1}}功能。
AnyCancellable
我想在您的情况下,操作员var cancellable: AnyCancellable?
cancellable = myPublisher
.sink(receiveValue: { value in
// Your logic.
cancellable.cancel()
})
正是您所需要的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。