2

I created an app with SwiftUI and when I try to display a button this error message appears:

Thread 1: Fatal error: No ObservableObject of type ModelData found. A View.environmentObject(_:) for ModelData may be missing as an ancestor of this view.

This occurs when I try to use an @EnvironmentObject when trying to display one of the views of my app.

My code is

struct OpportunityDetail: View {
    @EnvironmentObject var modelData: ModelData
    var opportunity: Opportunity
    
    var opportunityIndex: Int {
            modelData.opportunities.firstIndex(where: { $0.id == opportunity.id })!
        }
    
    
    var body: some View {
        ScrollView {
            
            MapView(coordinate: opportunity.locationCoordinate)
                .frame(height: 300)
                .ignoresSafeArea(edges: .top)
            
            CircleImage(opportunity: opportunity)
                .offset(y: -130)
                .padding(.bottom, -130)
            
            
            VStack {
                VStack(alignment: .leading) {
                    Text(opportunity.position)
                        .font(.title)
                    HStack {
                        Text(opportunity.name)
                            .font(.subheadline)
                        Spacer()
                        Text(opportunity.city)
                            .font(.subheadline)
                    }
                    .font(.subheadline)
                    .foregroundColor(.secondary)
                    
                    Divider()
                    Text("About the Opportunity")
                        .font(.title2)
                        Text(opportunity.description)
                    ApplyButton(isSet: $modelData.opportunities[opportunityIndex].isApplied)
                }
                .padding()
            }
        }
        .navigationTitle(opportunity.name)
        .navigationBarTitleDisplayMode(.inline)
    }
}

However, the preview and live preview of the View work fine


struct OpportunityDetail_Previews: PreviewProvider {
    
    static let modelData = ModelData()
    
    static var previews: some View {
        OpportunityDetail(opportunity: modelData.opportunities[0])
            .environmentObject(modelData)
    }
}

I know I have to pass my environment object somewhere but don't know how to. I would greatly appreciate anyone's help.

Shehran M.
  • 71
  • 4
  • 4
    You have to use `.environmentObject(modelData)`, just like you did for a preview, somewhere in the view hierarchy. For example, the parent view of `OpportunityDetail` could do it, or you can create it at the root level. For example, if `ContentView` is your root view, you can set it there. – New Dev Mar 01 '21 at 02:55

1 Answers1

5

My issue was solved by putting .environmentObject(modelData) into ContentView as it was the root view of all of my subviews as New Dev said:

You have to use .environmentObject(modelData), just like you did for a preview, somewhere in the view hierarchy. For example, the parent view of OpportunityDetail could do it, or you can create it at the root level. For example, if ContentView is your root view, you can set it there.

Shehran M.
  • 71
  • 4
  • Thank you for posting your solution. 2 days of pounding my head and moving my @StateObject declaration into my base view fixed it. Not sure why it doesn't propagate from the view that contains the NavigationStack but I'll go with it! – Janene Pappas Aug 07 '23 at 17:46