UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Fatal Error: No ObservableObject of type Order found.

Forums > SwiftUI

I am working through the SwiftUI starter project, but running under Xcode 12 beta 4. I am trying to get the project to run with the new format, iDineApp.swift instead of the SceneDelegat.swift. I have added envrionment objects to all the views to handle the order. I am not sure what I am missing though. The full error text when I build and run is

2020-08-15 10:42:26.865892-0400 iDine[58795:3690986] libMobileGestalt MobileGestaltCache.c:38: No persisted cache on this platform.
Fatal error: No ObservableObject of type Order found. A View.environmentObject(_:) for Order may be missing as an ancestor of this view.: file SwiftUI, line 0
2020-08-15 10:42:31.094675-0400 iDine[58795:3690785] Fatal error: No ObservableObject of type Order found. A View.environmentObject(_:) for Order may be missing as an ancestor of this view.: file SwiftUI, line 0

What am I missing?

3      

Could you please share your code otherwise helping you will be difficult

3      

Sure. I am working from this tutorial: https://www.hackingwithswift.com/quick-start/swiftui/swiftui-tutorial-building-a-complete-project

And am stuck on adding the tab view https://www.hackingwithswift.com/quick-start/swiftui/adding-tabview-and-tabitem

My main app code

@main
struct iDineApp: App {
    @EnvironmentObject var order: Order
    var body: some Scene {
        WindowGroup {
            AppView()
        }
    }
}

struct iDineApp_Previews: PreviewProvider {
    static let order = Order()

    static var previews: some View {
        AppView().environmentObject(order)
    }
}

The order

import SwiftUI

class Order: ObservableObject {
    @Published var items = [MenuItem]()

    var total: Int {
        if items.count > 0 {
            return items.reduce(0) { $0 + $1.price }
        } else {
            return 0
        }
    }

    func add(item: MenuItem) {
        items.append(item)
    }

    func remove(item: MenuItem) {
        if let index = items.firstIndex(of: item) {
            items.remove(at: index)
        }
    }
}

ContentView

struct ContentView: View {
    let menu = Bundle.main.decode([MenuSection].self, from: "menu.json")
    var body: some View {
        NavigationView{
            List {
                ForEach(menu) { section in
                    Section(header: Text(section.name)) {

                        ForEach(section.items) { item in
                            ItemRow(item: item)
                    }
                    }
                }
            }
            .navigationBarTitle("Menu")
            .listStyle(InsetGroupedListStyle())
        }
    }
}

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

ItemDetail

struct ItemDetail: View {
    @EnvironmentObject var order: Order

    var item: MenuItem
    var body: some View {
        VStack {
            ZStack(alignment: .bottomTrailing) {
                Image(item.mainImage)
                Text("Photo: \(item.photoCredit)")
                    .padding(4)
                    .background(Color.black)
                    .font(.caption)
                    .foregroundColor(.white)
                    .offset(x: -5, y: -5)
                    .opacity(0.75)
            }
            Text(item.description).padding()
            Button("Order This") {
                self.order.add(item: self.item)
            }.font(.headline)
            Spacer()
        }.navigationBarTitle(Text(item.name), displayMode: .inline)
    }
}

struct ItemDetail_Previews: PreviewProvider {
    static let order = Order()

    static var previews: some View {
        NavigationView
        {        ItemDetail(item: MenuItem.example).environmentObject(order)
        }
    }
}

OrderView

struct OrderView: View {
    @EnvironmentObject var order: Order

    var body: some View {
        NavigationView {
            List {
                Section {
                    ForEach(order.items) { item in
                        HStack {
                            Text(item.name)
                            Spacer()
                            Text("$\(item.price)")
                        }
                    }
                }

                Section {
                    NavigationLink(destination: Text("Check out")) {
                        Text("Place Order")
                    }
                }
            }
            .navigationBarTitle("Order")
            .listStyle(GroupedListStyle())
        }
    }
}

struct OrderView_Previews: PreviewProvider {
    static let order = Order()

    static var previews: some View {
        OrderView().environmentObject(order)
    }
}

AppView

struct ItemRow: View {
    static let colors: [String: Color] = ["D": .gray, "G": .yellow, "N": .orange, "S": .red, "V": .green]
    var item: MenuItem
    var body: some View {
        NavigationLink(destination: ItemDetail(item: item))
        {
            HStack {
                Image(item.thumbnailImage)
                    .clipShape(Circle())
                    .overlay(Circle().stroke(Color.gray, lineWidth: 2.0))
                VStack(alignment: .leading) {
                    Text(item.name)
                        .font(.headline)
                    Text("$\(item.price)")
                }

                Spacer()

                ForEach(item.restrictions, id: \.self) {
                    restriction in Text(restriction)
                        .font(.caption)
                        .fontWeight(.black)
                            .padding(5)
                            .background(Self.colors[restriction, default: .black])
                            .clipShape(Circle())
                            .foregroundColor(.white)
                }
            }
        }
    }
}

struct ItemRow_Previews: PreviewProvider {
    static var previews: some View {
        ItemRow(item: MenuItem.example)
    }
}

Item Row

struct ItemRow: View {
    static let colors: [String: Color] = ["D": .gray, "G": .yellow, "N": .orange, "S": .red, "V": .green]
    var item: MenuItem
    var body: some View {
        NavigationLink(destination: ItemDetail(item: item))
        {
            HStack {
                Image(item.thumbnailImage)
                    .clipShape(Circle())
                    .overlay(Circle().stroke(Color.gray, lineWidth: 2.0))
                VStack(alignment: .leading) {
                    Text(item.name)
                        .font(.headline)
                    Text("$\(item.price)")
                }

                Spacer()

                ForEach(item.restrictions, id: \.self) {
                    restriction in Text(restriction)
                        .font(.caption)
                        .fontWeight(.black)
                            .padding(5)
                            .background(Self.colors[restriction, default: .black])
                            .clipShape(Circle())
                            .foregroundColor(.white)
                }
            }
        }
    }
}

struct ItemRow_Previews: PreviewProvider {
    static var previews: some View {
        ItemRow(item: MenuItem.example)
    }
}

4      

struct iDineApp: App {
    @EnvironmentObject var order: Order

Here you indicate that the Environment should contain an object of type Order but you never actually create such an object to pass in. Just like how you created an Order in the iDineApp_Previews, you also need to create one in iDineApp:


@main
struct iDineApp: App {
    @StateObject private var order = Order()
    var body: some Scene {
        WindowGroup {
            AppView().environmentObject(order)
        }
    }
}```

3      

Thanks That fixed it.

3      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.