What's the best way, to delay a moment when a publisher sends some data in Swift Combine? Let's assume following situation:
private var publisher: PassthroughSubject<Progress, Error>
// closure called every second:
startWithProgress() { [weak self] progress in
self.publisher.send(.init(progress: progress))
// How to call this 0.5 second after the above `send`:
self.publisher.send(.init(progress: progress + 0.5))
}
I checked Delay
API, but it seems I'd need to create another publisher to make use of it, which is suboptimal in my case. I also checked throttle
and debounce
, but those also don't allow me to send 2 updates one after another, with a given delay between them.
There's a difference between delaying the act of sending the values - which you can do with DispatchQueue.asyncAfter
- and creating a combine pipeline that delays upstream values.
You haven't specified any details about what you are actually trying to accomplish, so it's hard to give a definitive answer.
If I was to generalize, it looks like that you want a pipeline that for each upstream value it emits the value, then emits the value + 0.5
again, but delayed. This could be done like below, as an example:
let duplicateAndDelay = publisher
.flatMap { [($0, 0), ($0 + 0.5, 0.5)].publisher } // duplicate
.flatMap { (progress, delay) in
Just(progress)
.delay(for: .seconds(delay), scheduler: RunLoop.main) // delay
}
Then you can just send
once:
startWithProgress() { [weak self] progress in
self?.publisher.send(progress)
}
and return the duplicateAndDelay
publisher, instead of the publisher
publisher, to be subscribed to.