Search code examples
swiftswiftuiobservable

How to handle state changes in View model?


I need to know what is the right way to make custom changes to model when Binding or Bindable var updates in UI. Specifically, here is my problem. I have my view model as follows:

enum ChosenControl {
   case none, option1, option2, option3
}

@Observable class CustomViewModel {
   var sliderVal: Float = 0.5
   var sliderMinVal: Float = 0.0
   var sliderMaxVal: Float = 1.0
   var chosenControl: ChosenControl = .none

   func chooseControl(_ controlOpt:ChosenControl) {
      sliderMinVal = getMinValForOpt(controlOpt)
      sliderVal =    getCurrentValForOpt(controlOpt)
      sliderMaxVal = getMaxValForOpt(controlOpt)
   }
}

I now create @Bindable from these three variables in ViewModel and hook it to slider in my SwiftUI view.

Slider(value: $customViewModel.sliderVal) { editing in
    print("Editing...")
}

My problem is I also want to perform custom actions in my model when sliderVal changes in UI (not otherwise, as sliderVal, sliderMinVal, sliderMaxVal can be changed programatically when user changes chosenControl through UI). What is the right way to do this?


Solution

  • You can define an interceptor-like property:

    let sliderValInterceptor = Binding<Float>(
        get: { customViewModel.sliderVal },
        set: {
            customViewModel.sliderVal = $0
            /* 👉 Do the extra work here 👈 */
        }
    )
    

    Then use it where you need:

    Slider(value: sliderValInterceptor) { editing in
        print("Editing...")
    }
    

    So setting the sliderValInterceptor will have extra effects that the original binding dont.