0

I am creating my first app and I am having trouble using @EnvironmentObject and @StateObject. When I run the simulator it opens my ContentView(). I am trying to get it to where it opens the MainView(), which has a tabView. And now the tabView is not showing my ContentView(). I am assuming I have the @EnvironmentObject and @StateObject in the wrong places. In my ContentView it shows a list and addButton. I am basically trying to have a program that is updated by the user by filling out a form.

Here is the Main Method

import SwiftUI

@main
struct Location_ScoutApp: App {
    
   @StateObject var listViewModels: ListViewModel = ListViewModel()
    
    var body: some Scene {
        WindowGroup {
          //  MainView(){
               ContentView()
            .environmentObject(listViewModels)
            //}
        }
    }
}

Here is my MainView.

import SwiftUI

struct MainView: View {
    
    var body: some View {
        
        TabView {
            MapView()
                .tabItem {
                    Label("Map", systemImage: "map.circle")
                }
// this is where i am having trouble.
            ContentView()
                .tabItem {
                    Label("Explore", systemImage: "magnifyingglass")
                
            }
            
            ProfileView()
                .tabItem {
                    Label("Profile", systemImage: "person.crop.circle")
                }
        }
    }

}
struct MainView_Previews: PreviewProvider {
    static var previews: some View {
        MainView()

    }
}

Here is my ContentView:

import SwiftUI

struct ContentView: View {
    @EnvironmentObject var listViewModel: ListViewModel
    
    var body: some View {
        List {
            ForEach(listViewModel.items) { item in
// this is where i am getting my new error.
                ListRowView(item: item)
                    .onTapGesture {
                        listViewModel.updateItem(item: item)
                    }
                
            }
        }
        
        .navigationTitle("Explore")
        .navigationBarItems(
            leading: EditButton(),
            trailing:
                NavigationLink("Add", destination: addALandmarkForm()))
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView {
        ContentView()
    }
        .environmentObject(ListViewModel())
    }
}
Zavien
  • 3
  • 2
  • In `Location_ScoutApp` you have `MainView()` commented out. You should use `MainView()` instead of `ContentView()` – jnpdx Dec 07 '21 at 18:36
  • When i did that it compiled, but when i ran it in the simulator it i got an error in my ContentView(). The error: "Thread 1: Fatal error: No ObservableObject of type ListViewModel found. A View.environmentObject(_:) for ListViewModel may be missing as an ancestor of this view." @jnpdx – Zavien Dec 07 '21 at 18:46
  • That doesn't happen when I try your code (with the sections you've left out stubbed out). Can you include a [mre]? – jnpdx Dec 07 '21 at 18:59
  • I added more code where ListViewModel comes from, basically when I run it the ContentView() tab crashes when i click on it. Does this Help? – Zavien Dec 07 '21 at 19:28
  • No, it doesn't, because your example still can't be compiled. Please try to include a [mre] that can be copied and pasted into Xcode. – jnpdx Dec 07 '21 at 19:30
  • I'm sorry i'm confused on how you want me to make a minimal reproducible example. When I run it I'm trying to click the tabview and when I do it crashes. It is supposed to open up a navigationView that displays a list of a information inputted by the user by clicking the add button, which brings up a form. – Zavien Dec 07 '21 at 20:05
  • I understand what you want to happen. But, what you're describing doesn't happen when I test your code (when I stub out the parts you haven't included). So, in order to get help, you're going to have to include something that others can reproduce. This means paring down your code to only what causes the issue and making sure you include all of the elements necessary to make it compile. That's what a [mre] is. In terms of *how* to make it, try pasting your code into a blank Xcode project and see what you aren't including. – jnpdx Dec 07 '21 at 20:07
  • I can't figure it out. I don't understand why your code runs and mine doesnt. I tried it in a new xcode but cant get it to work. I just need to prevent it from crashing when i hit the magnify button. – Zavien Dec 07 '21 at 21:28

1 Answers1

0

Without a reproducible example, it's hard to debug. This code, however, which is based on yours, works fine. Perhaps you can find the difference between your implementation and mine:


struct Item : Identifiable {
    var id = UUID()
    var title : String
}

class ListViewModel: ObservableObject {
    @Published var items : [Item] = [.init(title: "Test 1"),.init(title: "Test 2")]
}

@main
struct Location_ScoutApp: App {
    
   @StateObject var listViewModels: ListViewModel = ListViewModel()
    
    var body: some Scene {
        WindowGroup {
          MainView()
            .environmentObject(listViewModels)
        }
    }
}

struct MainView: View {
    
    var body: some View {
        
        TabView {
            Text("Map")
                .tabItem {
                    Label("Map", systemImage: "map.circle")
                }

            ContentView()
                .tabItem {
                    Label("Explore", systemImage: "magnifyingglass")
                
            }
            
            Text("profile")
                .tabItem {
                    Label("Profile", systemImage: "person.crop.circle")
                }
        }
    }

}

struct ContentView: View {
    @EnvironmentObject var listViewModel: ListViewModel
    
    var body: some View {
        NavigationView {
           List {
             ForEach(listViewModel.items) { item in
                 Text(item.title)
             }
           }
           .navigationTitle("Explore")
        }
    }
}

jnpdx
  • 45,847
  • 6
  • 64
  • 94
  • Ok i got it to work. i was missing the .environmentObject(listViewModels) under the main method. But now my navigation bar is not showing up. – Zavien Dec 07 '21 at 21:38
  • The only place you have a `NavigationView` is in your Preview. If you want it in your ContentView, you should add it there. I've updated my answer to show this. – jnpdx Dec 07 '21 at 21:40
  • THANK YOU SO MUCH!! This helped a lot. I have so much to learn. I'm sorry about the stupid questions and not being able to give you a minimal reproducible example. – Zavien Dec 07 '21 at 21:47
  • No problem. Please accept the answer using the green checkmark. – jnpdx Dec 07 '21 at 21:48