I'm new to Combine and I'd like to get a seemingly simple thing. Let's say I have a collection of integer, such as:
let myCollection = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I'd like to publish each element with a delay of, for example, 0.5 seconds.
print 0
wait for 0.5secs
print 1
wait for 0.5secs
and so forth
I can easily get the sequence publisher and print the elements like this:
let publisherCanc = myCollection.publisher.sink { value in
print(value)
}
But in this case all the values are printed immediately. How can I print the values with a delay? In Combine there's a .delay
modififer, but it's not for what I need (indeed, .delay
delays the entire stream and not the single elements). If I try:
let publisherCanc = myCollection.publisher.delay(for: .seconds(0.5), scheduler: RunLoop.main).sink { value in
print(value)
}
All I get it's just an "initial" delay, then the elements are printed immediately.
Thanks for your help.
Using the idea from the answer linked by Alexander in comments, you can create a publisher that emits a value every 0.5 seconds using Timer.publish(every:on:in:)
, then zip
that together with your Array.publisher
to make your downstream publisher emit a value every time both of your publishers have emitted a new value.
Publishers.Zip
takes the n-th element of its of its upstream publishers and only emits when both of its upstreams have reached n emitted values - hence by zipping together a publisher that only emits its values at 0.5 second
intervals with your original publisher that emits all of its values immediately, you delay each value by 0.5 seconds.
let delayPublisher = Timer.publish(every: 0.5, on: .main, in: .default).autoconnect()
let delayedValuesPublisher = Publishers.Zip(myCollection.publisher, delayPublisher)
let subscription = delayedValuesPublisher.sink { print($0.0) }