Pass data between view models in SwiftUI

I have a parent view and a child view. Both the parent and child view have their own view model. In the child view, the user can make a selection which is saved in a [String]. I want to use the values from the child view’s [String] in the parent view. What would the best way be to go about passing the data between the view models and thus the views?

I would prefer not to use an environment object, as these values will only be used in these two views.

Here are the view models as an example.

class ParentViewModel: ObservableObject {
    @Published var selectedExercise = [String]()
}
class ChildViewModel: ObservableObject {
    @Published var selectedExercise = [String]()
}

  • 2

    Too little information really but do you need two view models? What about passing the array to the child view as a Binding?

    – 

  • Either as suggested above, have a @Binding in child view, or if you have to have 2 view models for other reasons, you can for example keep selectedExercise in a child view model, and keep an instance of the ChildViewModel in the ParentViewModel, so when oyu load the child, you pass that instance from the parent, and parent uses selectedExercise from that same model

    – 




  • Note, it is not a good idea to nest ObservableObjects.

    – 

  • @workingdogsupportUkraine official source of that claim please? yes, nested observables can be tricky, but “not a good idea” is an overreaction. Really depends on the use

    – 

  • This is just my opinion that it is not a good idea, especially now that we have Observation. I based my opinion from these SO posts dealing with nested ObservableObjects, nested, nested observable, is it ok to nest

    – 

rIn SwiftUI the View struct holds the view data already so there is no need for any objects and it’s just:

struct ParentView: View {
    @State var selectedExercise = [String]()

    var body: some View {
        // read only
        ReadOnlyChildView(selectedExercise: selectedExercise) // or transform the selection via a computed property

        // or if you need read/write
        ReadWriteChildView(selectedExercise: $selectedExercise)
    }
}

and

struct ReadOnlyChildView: View {
   // read only 
   let selectedExercise: [String]

    var body: some View {
         // called when selectedExcercise value changes from last time this View was init
        ...
    }
}

struct ReadWriteChildView: View {
   // If read/write needed
   @Binding var selectedExercise: [String]  

   ...
}

If you do attempt to use objects instead of learning how the View structs work then you’ll basically be re-implementing SwiftUI which is a complete waste of time!

Leave a Comment