11

I'm trying to trigger the sliderchanged() function when the slider value changes, I might be missing something very basic but every similar thing I've found isn't working. Isn't there anything like "action" for the Slider or the old "ValueChanged" action?

Here's my code:

struct CustomSlider1: View {

    @State var progress: Float = 0.5
    var body: some View {

       VStack{
        Slider(value: $progress)
            .padding(.all)
            Text(String(progress))          
        }        
    }

    func sliderchanged() {
        //do things 
    }
}

Thanks!!

Gianclgar
  • 113
  • 1
  • 6
  • 1
    You can create an ObservableObject with an additional PassthroughPublisher as your bound variable in the slider. You can then attach an onReceive to the publisher and use it to invoke sliderChanged. Don't try objectWillChange as it is sent before that value is updated. – Michael Salmon Oct 16 '19 at 04:50
  • @Gianclgar Welcome to StackOverflow! If an answer below helped you figure out a solution, you should accept it. That way, programmers with a similar problem will know what worked for you. – RPatel99 Oct 19 '19 at 20:55

4 Answers4

32

You can make a custom Binding that calls the function in the Binding's setter:

@State var progress: Float = 0.5
var body: some View {

   VStack{
       Slider(value: Binding(get: {
           self.progress
       }, set: { (newVal) in
           self.progress = newVal
           self.sliderChanged()
       }))
       .padding(.all)
       Text(String(progress))
    }
}

func sliderChanged() {
    print("Slider value changed to \(progress)")
}
RPatel99
  • 7,448
  • 2
  • 37
  • 45
22

Swift 5, iOS 13

Another option, simple using a State variables and a closure.

@State var alpha = 65
@State var alphaToShow = ""

Slider(value: $alpha, in: 65...90,step: 1,onEditingChanged: { data in
  self.alphaToShow = String(Character(UnicodeScalar(Int(self.alpha))!))
  // execute more code here
}
}).padding()
Text(alphaToShow)
user3069232
  • 8,587
  • 7
  • 46
  • 87
5

Yet another approach to get continuous updates using onChange modifier.

import SwiftUI

struct SliderOnChange: View {
    @State var progress: Float = 0.5

    var body: some View {
        VStack{
            Slider(value: self.$progress)
                .onChange(of: self.progress) { newProgress in
                    self.sliderChanged(to: newProgress)
                }
            Text(String(self.progress))
        }
    }

    func sliderChanged(to progress: Float) {
        print("Slider value changed to \(progress)")
    }
}
Kousuke Ariga
  • 691
  • 9
  • 10
0

More Combine way:

import Combine

class ViewModel: ObservableObject {

    @Published var sliderValue: Double = 0
    private var subscriptions = [AnyCancellable]()
    
    init() {
        $sliderValue.sink(receiveValue: {
            print("sliderValue: ", $0)
        }).store(in: &subscriptions)
    }
}
Serhii Didanov
  • 2,200
  • 1
  • 16
  • 31