I'm working on a SwiftUI app using the MVVM architecture. I have the problem that I need to pass data from a parent View into its child viewModel, but I'm not sure how to pass a parameter from the view into the viewModel.
The child View which should own the viewModel is here:
struct InstanceView: View {
    @ObservedObject var instance: Instance
    
    @StateObject var viewModel = InstanceViewViewModel(instance: instance)
    var body: some View {
        ...
    }
}
And this is the viewModel:
class InstanceViewViewModel: ObservableObject {
    @ObservedObject var instance: Instance
    
    ...
}
Obviously the View doesn't work, I get the error Cannot use instance member 'instance' within property initializer; property initializers run before 'self' is available
If I try using init() in the View to assign a value to viewModel:
@ObservedObject var instance: Instance
@StateObject var viewModel: InstanceViewViewModel
init(instance: Instance) {
    self.instance = instance
    self.viewModel = InstanceViewViewModel(instance: instance)
}
But I get the error Cannot assign to property: 'viewModel' is a get-only property.
I have read that you should give the viewModel property (instance) a default value, and then set it in the View with .onAppear(). However, in my case, Instance is a Core Data object so I can't really create one to use as a default value.
I also read that I could maybe use _instance = StateObject(wrappedValue: InstanceViewViewModel(instance: instance)) in the View's init, and swiftUI would be smart enough to only initialize the StateObject once. However I'm pretty sure this is a bad practice.
I also can't use lazy on a StateObject
So is there any other way to achieve this? Could a solution be somehow getting the value InstanceView is being initialized with on this line:
@StateObject var viewModel = InstanceViewViewModel(instance: instance)
, outside of an init, so I don't need to reference self, like you would do inside of an init? (this is probably a stupid idea)
Or should I be implementing MVVM in a different way?
Thanks!
 
     
     
    