如何在PassthroughSubject发出nil时取消flatMap的Timer.publisher?
解决方案
你可以通过在flatMap的闭包中根据value是否为nil返回不同的发布者来实现需求:
情况1:收到nil时停止当前Timer,后续仍可响应非nil值
修改flatMap逻辑,当value为nil时返回一个立即完成的空发布者,这样会自动取消之前的Timer订阅,停止计时:
let stream = PassthroughSubject<String?, Never>() let repeated = stream.flatMap { value -> AnyPublisher<Date, Never> in guard value != nil else { // 返回立即完成的空发布者,终止当前Timer return Empty(completeImmediately: true).eraseToAnyPublisher() } return Timer.publish(every: 3, on: .main, in: .default) .autoconnect() .eraseToAnyPublisher() }
情况2:收到nil后彻底终止整个发布链,不再处理后续事件
如果希望一旦收到nil,整个repeated发布者就永久终止,不再响应后续的非nil值,可以结合prefix(while:)操作符:
let stream = PassthroughSubject<String?, Never>() let repeated = stream .prefix(while: { $0 != nil }) // 当检测到nil时,终止上游发布者 .flatMap { _ in Timer.publish(every: 3, on: .main, in: .default) .autoconnect() }
原理说明
Empty(completeImmediately: true)会立即发送完成事件,flatMap在切换到这个发布者时,会自动取消之前订阅的Timer,从而停止计时。prefix(while:)会让发布者在满足条件(这里是value != nil)时继续发送事件,一旦条件不满足,就发送完成事件,终止整个链的所有订阅。
内容的提问来源于stack exchange,提问作者Yotam
相关产品推荐
相关产品推荐

