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

如何用CurrentValueSubject从Timer Publisher获取上一日期并简化代码

使用CurrentValueSubject简化定时器时间差计算代码

方案一:用CurrentValueSubject替代显式存储变量

通过CurrentValueSubject可以直接维护并获取上一次的日期值,无需单独声明lastSampleUpdate变量,修改后的代码如下:

import Combine

var sampleTimer: AnyCancellable?
// 用CurrentValueSubject持久化当前日期,替代lastSampleUpdate
private let lastDateSubject = CurrentValueSubject<Date, Never>(Date())

func startSampling(on date: Date) {
    // 初始化subject的初始值为传入的起始日期
    lastDateSubject.send(date)
    
    sampleTimer = Timer.publish(every: 20, on: .main, in: .default)
        .autoconnect()
        .receive(on: RunLoop.main)
        .sink { newDate in
            // 从subject获取上一次的日期值
            let timeDifference = newDate.timeIntervalSince(lastDateSubject.value)
            print("\(timeDifference) seconds passed")
            // 更新subject的当前值为新日期
            lastDateSubject.send(newDate)
        }
}

关键改动说明

  • 移除了原有的lastSampleUpdate变量,改用CurrentValueSubject<Date, Never>来存储当前日期:它既可以保存当前值,也能作为数据流的载体,符合Combine响应式编程的思路。
  • 在startSampling方法中,先通过send(_:)将传入的起始日期设置为subject的初始值。
  • 定时器的sink闭包直接处理时间差计算和值更新:从lastDateSubject.value拿到上一次的日期,计算差值后再更新subject的当前值,替代了原有的newDate函数。

方案二:用scan操作符实现(无需额外Subject)

如果不想引入CurrentValueSubject,也可以用scan操作符直接在数据流中累积上一次的日期值,同样能移除显式变量:

import Combine

var sampleTimer: AnyCancellable?

func startSampling(on date: Date) {
    sampleTimer = Timer.publish(every: 20, on: .main, in: .default)
        .autoconnect()
        .receive(on: RunLoop.main)
        // scan操作符会累积上一次的输出值,初始值为传入的date
        .scan(date) { lastDate, newDate in
            let timeDifference = newDate.timeIntervalSince(lastDate)
            print("\(timeDifference) seconds passed")
            return newDate
        }
        .sink(receiveValue: { _ in })
}

scan会在每次收到新的日期时,结合上一次累积的值执行闭包逻辑,最后返回新的累积值,全程无需额外存储变量。


内容的提问来源于stack exchange,提问作者Daniel K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 13:45:26