ohhh, that's a tough one. @StateObject is definitely making things easier, but the trick we've used for now (we’re still targeting iOS 13) is to wrap ViewModels in @State in a parent view, and pass it down to your view as an @EnvironmentObject.
When the subview changes/re-renders, your ViewModel stay the same on the parent view and is not recreated as it is a @State; and your subview can still listen to @PUublished changes.
We've made a generic wrapper for it, and we use almost everywhere:
struct ViewModelWrapper<V: View, ViewModel: ObservableObject>: View {
private let contentView: V
@State private var contentViewModel: ViewModel
init(contentView: @autoclosure () -> V, vm: @autoclosure () -> ViewModel) {
self._contentViewModel = State(initialValue: vm())
self.contentView = contentView()
}
var body: some View {
contentView
.environmentObject(contentViewModel)
}
}
Comments
ohhh, that's a tough one. @StateObject is definitely making things easier, but the trick we've used for now (we’re still targeting iOS 13) is to wrap ViewModels in @State in a parent view, and pass it down to your view as an @EnvironmentObject.
When the subview changes/re-renders, your ViewModel stay the same on the parent view and is not recreated as it is a @State; and your subview can still listen to @PUublished changes.
We've made a generic wrapper for it, and we use almost everywhere: