0

I'm building the a metronome with swiftUI

I have a @State var that connect to a slider.

@State private var period: Double
Slider(value: period, in: 0.25...5, step: 0.25)
          

Right now I can only reset the time interval if I restart the metronome.

Button(action: { startStop = !startStop
    self.timer = Timer.publish(every: self.period, on: .main, in:.default).autoconnect()
            } ){
                Text("START/STOP")
            }

However, I want to trigger the "self.timer = Timer.publish(...." whenever the slider is moved. Is there a way to trigger an ObservableObject @Published var whenever a @State var is changed? So that I can use ".onReceive()" function to trigger "self.timer = Timer.publish(...."

Thank you

Linus
  • 69
  • 4
  • Not directly answering your question, but I just want to make sure that you know that if this is any more than an experiment, `Timer` or `DispatchQueue` are nowhere near reliable enough to actually make a metronome with precise timing. – jnpdx May 14 '21 at 04:10

1 Answers1

0

The easiest way to perform code when a @State value changes is to add an onChange modifier to a child view of the view where you defined your @State, e.g.:

struct ContentView: View {
    @State private var period: Double = 0.5

    var body: some View {
        Slider(value: period, in: 0.25...5, step: 0.25)
          .onChange(of: period) { newValue in
            // perform your code here
          }
    }
}

See also Apple's documentation and an example on Hacking With Swift.

ScottM
  • 7,108
  • 1
  • 25
  • 42
  • Hi Scott My Slider is in a subview of ContentView, it is the only way that pass the "timer" to the subview? Thank you – Linus May 14 '21 at 14:25
  • onChange needs OSX Big Sur, I use "onEditingChanged" instead – Linus May 14 '21 at 15:50