0

I am having a view with two environment objects. I am displaying data from one of them, and modify data on the other one. When I change the data on the first object, another instance will be created of the second object and its data is cleared.

I created a code example that reproduce the issue, if you run this on preview, and tap on the increment button twice, you will see List is empty!

The list is only loaded on the onAppear block and this will not be called again when the view is created after the counter update.

struct ContentView: View {
    @EnvironmentObject var appState: AppState

    var body: some View {
        VStack {
            View1()
                .environmentObject(ListWrapper())
        }
    }
}

struct View1: View {
    @EnvironmentObject var listWrapper: ListWrapper
    @EnvironmentObject var appState: AppState
    
    var body: some View {
        VStack {
            HStack {
                Text("Counter:")
                Text("\(appState.counter)")
            }
            HStack {
                Button("+") { appState.increment() }.padding(.horizontal, 20)
                Divider()
                Button("-") { appState.decrement() }.padding(.horizontal, 20)
            }.overlay(Rectangle().stroke(Color.accentColor))
            .frame(height: 30)
            List {
                if listWrapper.list.count == 0 {
                    Text("List is empty!")
                } else {
                    ForEach(listWrapper.list, id:\.self) {
                        Text($0)
                    }
                }
            }
        }.onAppear { listWrapper.load() }
    }
}

class ListWrapper: ObservableObject {
    @Published var list: [String] = []

    func load() { list = ["1", "2", "3"] }
}

class AppState: ObservableObject {
    @Published var counter: Int = 0
    
    func increment() { counter += 1 }
    func decrement() { counter -= 1 }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environmentObject(AppState())
    }
}

Can someone explain what's the problem and how to fix it?

Noura
  • 722
  • 10
  • 24

1 Answers1

0

EnvironmentObjects must be supplied by anscestor views! >>> GO TO >>> WindowGroup

ContentView()
   .environmentObject(AppState())       // << Here: 1
   .environmentObject(ListWrapper())    // << Here: 2 

    struct View1: View {
    
    @EnvironmentObject var listWrapper: ListWrapper
    @EnvironmentObject var appState: AppState
    
    var body: some View {
        
        VStack {

            HStack {
                Text("Counter:")
                Text("\(appState.counter)")
            }

            HStack {
                Button("+") {
                    
                    appState.increment()
                    listWrapper.list.append(appState.counter.description)        // << Here: 3
                    
                }.padding(.horizontal, 20)
                Divider()
                Button("-") {
                    
                    appState.decrement()
                    listWrapper.list.append(appState.counter.description)        // << Here: 4
                    
                }.padding(.horizontal, 20)
            }
            .overlay(Rectangle().stroke(Color.accentColor))
            .frame(height: 30)
            
            
            List {
                
                
                if listWrapper.list.count == 0 {
                    Text("List is empty!")
                }
                else {
                    ForEach(listWrapper.list, id:\.self) { item in
                        Text(item)
                    }
                }
 
            }
 
        }.onAppear { listWrapper.load() }
    }
}
ios coder
  • 1
  • 4
  • 31
  • 91