问题
I have created an ObservableObject in a View.
@ObservedObject var selectionModel = FilterSelectionModel()
I put a breakpoint inside the FilterSelectionModel
's init
function and it is called multiple times. Because this View is part of a NavigationLink
, I understand that it gets created then and along with it, the selectionModel. When I navigate to the View, the selectionModel is created again.
In this same View I have a "sub View" where I pass the selectionModel as an EnvironmentObject
so the sub-view can change it.
AddFilterScreen().environmentObject(self.selectionModel)
When the sub view is dismissed, the selectionModel is once more created and the changes made to it have disappeared.
Interesting Note: At the very top level is a NavigationView
. IF I add
.navigationViewStyle(StackNavigationViewStyle())
to this NavigationView
, my selectionModel's changes disappear. BUT if I do not add the navigationStyle
, the selectionModel's changes made in the sub view remain!! (But I don't want a split nav view, I want a stacked nav view)
In both cases - with or without the navigationStyle
, the selectionModel is created multiple times. I can't wrap my head around how any of this is supposed to work reliably.
回答1:
You can instantiate the observable object in the init method, in this way you will be able to hold its value or the value won't disappear.
Instantiate this way in the view file.
@ObservedObject var selectionModel : FilterSelectionModel
init() {
selectionModel = FilterSelectionModel(value : "value to be saved from disappearing")
}
Instantiate this way in the viewModel file.
class FilterSelectionModel : ObservableObject {
@Published var value : String
init(value : String) {
self.value = value
}
}
This is a workaround that I found, but still, the init method is called multiple times and I didn't get any success with this issue.
In order to stop multiple initializing of the ViewModels as the view is declared in the Navigation View and SwiftUI uses struct which is a value type, so eventually these are initialized before the view is presented, therefore you can convert that view into a LazyView, so that it will only be initialized once the view is about to be presented or shown.
// Use this to delay instantiation when using `NavigationLink`, etc...
struct LazyView<Content: View>: View {
var content: () -> Content
var body: some View {
self.content()
}
}
You can call it like this...
NavigationLink(destination: LazyView { ViewTobePresented() })
来源:https://stackoverflow.com/questions/59533407/swiftui-observableobject-created-multiple-times