0

I have this class:

class MyModel:ObservableObject {
  
  var selectedObjectIndex:Int {
    set {}
    get {
      let selectedResult = objects.filter({ $0 == selectedObject })
      if selectedResult == 0 { return 0 }
      return objects.firstIndex(of: selectedResult.first!)!
    }
  }
}

This selectedObjectIndex would normally be a @Published var selectedObjectIndex:Int but because it is a computed property, I cannot use @Published there.

So I was forced to add this to the model

func getselectedObjectIndexBinding() -> Binding<Int> { 
  let binding = Binding<Int>(
    get: { () -> Int in
      return self.selectedObjectIndex
    }) { (newValue) in
    self.selectedObjectIndex = newValue
  }
  return binding
}

In the view I have a Picker, using this like

Picker(selection: myModel.getselectedObjectIndexBinding(),
       label: Text("select")) {

The picker appears correctly but If I set a new value on it, the model selectedObjectIndex is not updated.

3
  • 1
    Your set method for selectedObjectIndex does nothing Commented Feb 24, 2021 at 11:34
  • how do I solve that? Commented Feb 24, 2021 at 11:40
  • That depends on what do you want to be persistent (ie store) on selectedObjectIndex.set. From your code the intention is not clear - would you elaborate more? Commented Feb 24, 2021 at 13:19

1 Answer 1

1

You can try something like below, whenever a binding is updated, your selectedObjectIndex can trigger ObjectWillChange notification after doing some relevant work. I have created selectedObjectIndex as propertyObserver.

struct CreditCardFront: View {
    
    @ObservedObject var myModel:MyModel
   
   
    var body: some View {
        
        Picker(selection: myModel.getselectedObjectIndexBinding(),
               label: Text("select")) {
            
            ForEach(1..<10) { value in
                Text("\(value)")
            }
        }
        Text("\(myModel.selectedObjectIndex ?? 0)")
        
    }
    
    
}

class MyModel:ObservableObject {
    
    var selectedObjectIndex:Int?{
        didSet{
            // Your work here
            update() // call notification on specific change
        }
    }
    
    func getselectedObjectIndexBinding() -> Binding<Int> {
        let binding = Binding<Int>(
            get: { () -> Int in
                return self.selectedObjectIndex ?? 0
            }) { (newValue) in
            self.selectedObjectIndex = newValue
        }
        return binding
    }
    
    func update(){
        self.objectWillChange.send()
    }
}

@main-:

@main
struct WaveViewApp: App {
    @StateObject var model:MyModel
    init() {
        let model = MyModel()
        _model = StateObject(wrappedValue: model)
    }
    
    var body: some Scene {
        WindowGroup {
            CreditCardFront(myModel: model)
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Why not just @StateObject var model = MyModel()?
@pawello2222 we could definitely do that, but I had a old code snippet written that way which I just modified.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.