Search code examples
swiftswiftuicombinepublisher

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)
            }

    }

}

Solution

  • 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).