TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

SOLVED: Fatal error: No ObservableObject found.

Forums > SwiftUI

I got this error in my AppView : Fatal error: No ObservableObject of type GetData found. A View.environmentObject(_:) for GetData may be missing as an ancestor of this view.

I'm looking for a solution all days. How can I fix it?

FinalProjectApp.swift

import SwiftUI
import SwiftData
import Firebase
import FirebaseAuth

@main
struct FinalProjectApp: App {
    @StateObject var data = AllDrinks()
    @StateObject var gd = GetData()

    init(){
        FirebaseApp.configure()
    }
    var body: some Scene {
        WindowGroup {
            if Auth.auth().currentUser != nil  {
                AppView()
                    .environmentObject(data)
                    .environmentObject(gd)
            } else {
                ContentView()
                    .environmentObject(data)
                    .environmentObject(gd)
            }
        }
    }
}

AppView.swift

import SwiftUI
import FirebaseFirestore
import FirebaseFirestoreSwift
import FirebaseAuth

struct AppView: View{

    @EnvironmentObject var data: AllDrinks
    @EnvironmentObject var gd: GetData
    @State var name: String?

    init() {
        UITabBar.appearance().backgroundColor = UIColor.wootea
        if let user = Auth.auth().currentUser{
            gd.user_name = user.displayName ?? ""
            //gd.setName(name: (user.displayName ?? ""))
            //gd.fav_path = "user/" + (user.displayName ?? "") + "/favorite"
            //gd.order_path = "user/" + (user.displayName ?? "") + "/order"
            print("AppView name:\(gd.user_name)")
            //print("AppView fav_path:\(gd.fav_path)")
            //print("AppView order_path:\(gd.order_path)")
        }
    }
    var body: some View{
        TabView{
            HomeView()
                .tabItem{
                    Label("", systemImage: "house")
                }
//            FavoriteView()
//                .tabItem{
//                    Label("", systemImage: "heart")
//                }
//            OrderView()
//                .tabItem{
//                    Label("", systemImage: "cart")
//                }
//            AccountView()
//                .tabItem{
//                    Label("", systemImage: "person")
//                }
        }
        .tabViewStyle(DefaultTabViewStyle())
        .environmentObject(data)
        .environmentObject(gd)
    }

}

struct AppView_Previews: PreviewProvider {
    static var previews: some View {
        AppView()
            .environmentObject(AllDrinks())
            .environmentObject(GetData())
    }
}

ContentView.swift

import SwiftUI
import SwiftData
import FirebaseAuth

struct ContentView: View {

    @State private var email = ""
    @State private var password = ""
    @State private var alertTitle = ""
    @State private var showAlert = false
    @State var showBool = false
    @EnvironmentObject var gd: GetData
    @EnvironmentObject var data: AllDrinks

    var body: some View {
        NavigationStack{
            ZStack{
                VStack{
                    Color(.white)
                        .ignoresSafeArea()
                    Color(.orange)
                        .ignoresSafeArea()
                }
                VStack{
                    Image("logo")
                        .resizable()
                        .scaledToFill()
                        .frame(width: 400, height: 400)
                    Spacer()
                    Group{
                        TextField("Email", text: $email, prompt: Text("Email"))
                            .textFieldStyle(.roundedBorder)
                            .padding()
                        SecureField("Password", text: $password)
                            .textFieldStyle(.roundedBorder)
                            .padding()
                    }
                    .font(Font.system(size: 25, design: .default))
                    Spacer()

                    HStack(spacing: 30){
                        Button{
                            login()
                        } label: {
                            Text("Login")
                                .foregroundColor(.white)
                                .font(.title2)
                                .fontWeight(.semibold)
                        }
                        .padding()
                        .background(Color.black)
                        .cornerRadius(40)
                        .fullScreenCover(isPresented: $showBool){
                            AppView()
                        }
                        .alert(alertTitle, isPresented: $showAlert){
                            Button("OK"){}
                        } message: {
                            Text("")
                        }
                        NavigationLink {
                            SignUpView()
                        } label: {
                            Text("Sign Up")
                                .foregroundColor(.black)
                                .font(.title2)
                                .fontWeight(.semibold)
                        }
                        .padding()
                        .background(Color.white)
                        .cornerRadius(40)
                    }
                } // vstack
            } // zstack
        } // nav
        .environmentObject(gd)
        .environmentObject(data)
    } // body

    func login(){
        Auth.auth().signIn(withEmail: email, password: password){ result, error in
            guard error == nil else {
                if let message = error?.localizedDescription {
                    alertTitle = message
                }
                showAlert = true
                return
            }
            if let user = Auth.auth().currentUser{
                gd.user_name = user.displayName ?? ""
                gd.fav_path = "user/" + (user.displayName ?? "") + "/favorite"
                gd.order_path = "user/" + (user.displayName ?? "") + "/order"
                print("ContentView name:\(gd.user_name)")
                print("ContentView fav_path:\(gd.fav_path)")
                print("CintentView order_path:\(gd.order_path)")
            }
            alertTitle = "success"
            showBool = true
        }
    }
}

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

Drink.swift

import Foundation
import FirebaseFirestore
import FirebaseFirestoreSwift
import FirebaseAuth

class GetData: ObservableObject {
    @Published var user_name: String = ""
    @Published var fav_path: String = ""
    @Published var order_path: String = ""

    func getName() -> String{
        if let user = Auth.auth().currentUser{
            user_name = user.displayName ?? ""
            if user_name != nil{
                print("User:\(user_name)")
            }
        }
        return user_name
    }

    func setName(name:String){
        user_name = name;
    }

    func getFavpath() -> String{
        var name =  getName()
        fav_path = "user/" + name + "/favorite"
        return fav_path
    }

    func getOrderpath() -> String{
        var name = getName()
        order_path = "user/" + name + "/order"
        return order_path
    }
}

class AllDrinks: ObservableObject{

    @Published var allDrinks = [Drink]()
    @Published var orders = [Drink]()
    @Published var total = 0

    func calTotal(){
        total = 0
        for i in orders.indices{
            total += orders[i].price
        }
    }

    // clear placed orders
    func removeOrder(){
        orders.removeAll()
        total = 0
    }

    // update all drink data
    func createDrink(drink: Drink){
        let db = Firestore.firestore()
        do{
            try db.collection("drink").document("\(drink.name)").setData(from: drink)
        } catch {
            print(error)
        }
    }
    /*
    // update my favorite drink data
    func updateFavoriate() {
        for drink in allDrinks{
            createDrink(drink: drink)
        }
    }
    */

    // revise favorite data
    func modifyFavorite(fav: Favorite, id: String) {
        let db = Firestore.firestore()
        do{
            if let user = Auth.auth().currentUser{
                var user_name: String? = user.displayName
                if user_name != nil{
                    try db.collection("user").document(user_name ?? "").collection("favorite").document(id).setData(from: fav)
                    print("modifyFavorite Success")
                }
            }
        } catch {
            print(error)
        }
    }
}

struct Drink: Codable, Identifiable{
    var name: String
    var description: String
    var Mprice: Int
    var Lprice: Int
    var hasHot: Bool = true
    var isFavorite: Bool = false
    var type: String
    @DocumentID var id: String?

    var size: String = "M"
    var ice: String = "Normal"
    var sugar: String = "Normal"
    var price: Int = 0
}

struct Favorite: Codable, Identifiable{
    var name: String
    @DocumentID var id: String?
}

2      

In your ContentView and AppView you don't need the .environmentObject() modifier. You need it only once at the top.

3      

Thanks, I already solved it!

2      

Hacking with Swift is sponsored by RevenueCat.

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

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

Reply to this topic…

You need to create an account or log in to reply.

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.