Sorin Lica
Sorin Lica

Reputation: 7636

How to make a Combine publisher that publish values continuously?

I need a publisher that publish values from 1 to 360 continuously with a certain time interval between values.

I have this publisher that publish one value from 1 to 360 at every second, but once it reaches 360 it stops, basically (1...360).publisher stops providing values, but I need the publisher to keep publishing values starting again from 1

Probably it will work to add a condition if value == 360 then reset the publisher, but this would be inefficient since the condition will be put for every single value, any idea for a better solution?

struct ContentView: View {

let delayedValuesPublisher = Publishers.Zip((1...360).publisher,
                                            Timer.publish(every: 1, on: .main, in: .default)
                                                .autoconnect())



  var body: some View {

        Text("")
            .onReceive(delayedValuesPublisher) { (output) in
                print(output.0)
            }

    }

}

Upvotes: 2

Views: 1520

Answers (1)

Cristik
Cristik

Reputation: 32782

You don't need 3 publishers here (the timer, the numbers producers, the zipped one), one pipeline would suffice:

let delayedValuesPublisher = Timer
    .publish(every: 1, on: .main, in: .default)
    .autoconnect()
    .scan(0, { val, _ in val % 360 + 1 })

scan works like reduce on collections, by producing the next element based on a transform of the accumulated value and the value produced by the publisher (which we ignore, as we don't care about the Date produced by the timer).

Upvotes: 4

Related Questions