You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 11:15:05