如何立即触发 Timer.publish() ?

How to trigger Timer.publish() right away?

我创建了一个 timer via combine,它使用以下代码发出 Date 并忽略错误:

let timer: AnyPublisher<Date, Never> = Timer.publish(every: 5, on: .main, in: RunLoop.Mode.common)
  .autoconnect()
  .map { _ in Date() }
  .replaceError(with: Date())
  .eraseToAnyPublisher()

(我确信有比映射和替换错误更好的方法,但对于这个例子,我想保持类型简单,AnyPublisher<Date, Never>。)

计时器正确触发,但从创建计时器到第一次触发之间存在延迟(即等待 5 秒)。用 NSTimer, we can invoke timer.fire() 强制它立即开火。

在使用 Timer.publish() 时是否有等效的方法强制计时器立即 post?


或者,有没有办法将 Just(Date()) 与上面的 Timer.publish 合并,以便它立即每 5 秒触发一次,同时仍然保持 AnyPublisher<Date, Never> 类型?

I'm sure there are better ways than mapping and replacing the error

Timer.TimerPublisher.FailureNever,因此您不需要任何映射,因为它不会失败。

此外,Timer.TimerPublisher.Output已经是当前的Date(),所以你也不需要map输出。

要在订阅时立即发出当前日期,您需要将 Deferred { Just(Date()) } 与计时器发布者结合使用。 Deferred 表示在订阅发生之前不会计算当前日期。

这是一种将它们组合在一起的方法:

let timer = Deferred { Just(Date()) }
    .append(Timer.publish(every: 5, on: .main, in: .common).autoconnect())
    .eraseToAnyPublisher()

替代@rob mayoff 回答和@Senseful 评论,可以合并计时器的“第一个值”:

let delayPublisher = Timer.publish(every: 5, on: .main, in: .common)
  .autoconnect()
  .receive(on: RunLoop.main)
  .merge(with: Just(Date()))

此外,还有一个选项使用 prepend

let delayPublisher = Timer.publish(every: 5, on: .main, in: .common)
  .autoconnect()
  .receive(on: RunLoop.main)
  .prepend(Date())