I have a view called PurchaseView
. This view displays details about the purchase, what was purchased and who purchased it. What I'm doing is that in this view im putting both the ItemView
and ClientView
inside PurchaseView
. ItemView
and ClientView
are shared and there are used in other parts of my app. They have their own ViewModels.
I have also tried to put ItemViewModel
and ClientViewModel
inside PurchaseViewModel
but I do not know if it is ok to put an ObservableObject
inside another ObservableObject
. Is this a good approach or there should not be any ObservableObject
inside an ObservableObject
? Which one of the following is better?
This?
class PurchaseViewModel: ObservableObject {
let clientViewModel: ClientViewModel
let itemsViewModel: ItemViewModel
//
}
Or this?
struct PurchaseView: View {
@ObservedObject var purchaseViewModel: PurchaseViewModel
@ObservedObject var itemViewModel: ItemViewModel
@ObservedObject var clientViewModel: ClientViewModel
var body: some View {
//
}
}
Purchase model:
class Purchase {
let id: String
let total: Double
// ...
var item: Item?
var client: Client?
}
Your first solution will not work as the changes to the nested ObservableObjects aren't propagated upwards:
class PurchaseViewModel: ObservableObject {
let clientViewModel: ClientViewModel
let itemsViewModel: ItemViewModel
...
}
A workaround can be found here: How to tell SwiftUI views to bind to nested ObservableObjects.
Your second approach is right and will work for most cases:
struct PurchaseView: View {
@ObservedObject var purchaseViewModel: PurchaseViewModel
@ObservedObject var itemViewModel: ItemViewModel
@ObservedObject var clientViewModel: ClientViewModel
...
}
If you share an ObservableObject
for many views you can inject it to the environment instead and access as an @EnvironmentObject
.
Alternatively you can make your nested ObservableObjects to be structs:
class PurchaseViewModel: ObservableObject {
@Published var clientViewModel: ClientViewModel // <- add `@Published`
...
}
struct ClientViewModel { // <- use `struct` instead of `class`
...
}
Note that your ClientViewModel
will become a new struct every time it (or any of its properties) changes - this solution shouldn't be overused (especially for complex ViewModels).
Just noting that I'm using the NestedObservableObject
approach from How to tell SwiftUI views to bind to nested ObservableObjects.
Normally I'd avoid this but the nested object in question is actually a CoreData model so breaking things out into smaller views doesn't really work in this regard.
Since the world treats NSManagedObjects as (mostly) ObservableObjects, this solution seemed best.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With