Here is my issue: MainView
displays ChildView
and gives it an EnvironmentObject
containing a set of selected items.
ChildView
displays a list of selectable items(2 items in the example), and load the list when appearing.
The problem is that the ChildView
content is reset to its original value (1 item in the example) when I tap on any row.
I tried to make my code as compact as possible.
struct MainView: View {
@ObservedObject var model = MainViewModel()
var body: some View {
NavigationView {
ChildView().environmentObject(self.model)
}
}
}
class MainViewModel: ObservableObject {
@Published var selection = Set<Stuff>()
var formatted: String {
return "\(self.selection.count)"
}
}
struct ChildView : View {
@ObservedObject var cm = ChildViewModel()
@EnvironmentObject var model: MainViewModel
var body: some View {
VStack(spacing: 0) {
List(cm.demoData, id: \.self, selection: $model.selection) { stuff in
Text("\(stuff.value)")
}
.environment(\.editMode, .constant(EditMode.active))
.onAppear(perform: cm.load)
}
}
}
class ChildViewModel : ObservableObject {
@Published var demoData: [Stuff] = [Stuff(id: 1, value: "1")]
func load() {
self.demoData = [Stuff(id: 1, value: "1"), Stuff(id: 2, value: "2")]
}
}
struct Stuff : Identifiable, Equatable, Hashable {
var id: Int
var value: String
}
There is no problem if I don't use an environment object, but don't get how that causes the list to reset.
You modify
MainViewModel
and it cause rebuild body, includingChildView
.If you have iOS 14 as target minimal supported system the simplest solution is to use
StateObject
as it preserves view data