Is there a way to call a function when a slider is used in swift?

Viewed 57

I have a settings view, where I use a Slider to change a variable. Is there a way to execute code only when the variable is changed with the slider? I tried .onchange() and the problem that I have is, that even if I don't use the slider, but change the variable with another Picker Input, the code is executed.

 Slider(value: $noteLength, in: 0.1...3.01, step: 0.1)
                            .onChange(of: noteLength, perform:  { value in
                                defaults.set(value, forKey: "noteLengthEx1")
                                levelIndex = 4
                            })

Picker("Level", selection: $levelIndex) {
    ForEach(0 ..< levelOptions.count) {
        Text(self.levelOptions[$0])}
            .onChange(of: levelIndex, perform:  {
                levelIndex = 1
                noteLength = 1.0})
}

The code is a bit simplified, but if I use the Picker, noteLength will be changes to 1 and so the .onchange of the slider will be executed. That part I am trying to avoid.

Thanks and have a nice day :)

3 Answers

We can use computable in-inline binding with side-effect for this (and you can remove onChange at all), here is a demo

 Slider(value: Binding(get: { noteLength }, 
     set: { 
        // willSet side-effect here       // << here !!
        noteLenght = $0
        // didSet side-effect here       // << here !!
     }), 
    in: 0.1...3.01, step: 0.1)
    .onChange(of: noteLength, perform:  { value in
        defaults.set(value, forKey: "noteLengthEx1")
        levelIndex = 4
    })

actually you have to use a different variable for that as far as I know. actually if you change externally the noteLength I think is also adjusting the slider. isn't it?

I had the same problem with Toggle() and Picker() and solved it the same way. Took a little time to figure it out, so for anyone who is having the same issue:

Toggle("Notes can be the same", isOn: Binding(get: {equalNotes}, set: {
    equalNotes = $0
    // side-effects here
    }))
                    
Picker("tone difference", selection: Binding(get: {toneDifferenceIndex}, set: {
    toneDifferenceIndex = $0
    // side-effects here
}), content: {
    ForEach(0 ..< toneDifferenceOptions.count) {
        Text(self.toneDifferenceOptions[$0])
                          }
                      })

Related