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

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      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

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.