Swift Combine:仅监听publisher1时如何获取publisher2的最新值?
在Swift Combine中仅响应指定发布者变更并获取另一发布者的最新值
假设有两个发布者:
let publisher1 = AnyPublisher<String, Never>() let publisher2 = AnyPublisher<Int, Never>()
注:发布者的具体类型不影响问题本身。
需求是:仅在publisher1发送新值时触发订阅处理,但在处理过程中能获取publisher2的最新值。
如果直接使用CombineLatest:
let combinedPublisher = Publishers.CombineLatest(publisher1, publisher2)
会导致publisher2更新时也触发整个流,不符合仅响应publisher1变更的需求。
具体业务场景问题
在ViewModel中,我们用一个发布者触发屏幕刷新,流处理过程中需要用ViewModel的最新状态生成新发布者,但为了避免并发问题,不想直接访问状态属性。当前代码如下:
@Published private(set) var myState: State = .initial func bindMyData() { myRefreshUseCase.publisher .receive(on: DispatchQueue.ui) .combineLatest($myState) // 希望获取最新state,但不想State更新时触发整个流 .map { _, oldState in fetchNewDataPublisher(preapend: oldState) } .switchToLatest() .assign(to: \.loadingState, onWeak: self) .store(in: &disposables) }
解决方案:使用withLatestFrom操作符
withLatestFrom的特性是仅当左侧上游发布者(触发源)发送新值时,才会从右侧发布者取最新值合并输出,右侧发布者更新时不会触发整个流,完全匹配需求。
修改后的代码:
@Published private(set) var myState: State = .initial func bindMyData() { myRefreshUseCase.publisher .receive(on: DispatchQueue.ui) .withLatestFrom($myState) // 仅当前发布者更新时,获取myState的最新值 .map { _, latestState in fetchNewDataPublisher(preapend: latestState) } .switchToLatest() .assign(to: \.loadingState, onWeak: self) .store(in: &disposables) }
这个方案既保证了每次触发刷新时能拿到myState的最新值,又避免了状态更新时误触发流的问题,同时规避了直接访问属性可能带来的并发风险。
内容的提问来源于stack exchange,提问作者Amadeu Cavalcante Filho
相关产品推荐
相关产品推荐

