You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI报错:未找到GetData类型ObservableObject的解决求助

问题:Fatal error: No ObservableObject of type GetData found

在AppView中遇到致命错误:

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

已尝试在AppView()和ContentView()中添加.environmentObject(GetData()),同时在AppView的TabView以及ContentView的body中添加.environmentObject(gd),但问题仍未解决。


相关代码

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 ?? ""
            print("AppView name:\(gd.user_name)")
        }
    }
    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?
}

修复方案

1. 修正AppView中初始化阶段访问EnvironmentObject的错误

@EnvironmentObject在View的init方法中还未完成注入,此时直接访问会导致崩溃。将用户信息赋值逻辑移到onAppear回调中:

struct AppView: View{
    @EnvironmentObject var data: AllDrinks
    @EnvironmentObject var gd: GetData
    @State var name: String?

    init() {
        UITabBar.appearance().backgroundColor = UIColor.wootea
        // 移除init中访问gd的代码
    }
    
    var body: some View{
        TabView{
            HomeView()
                .tabItem{
                    Label("", systemImage: "house")
                }
        }
        .tabViewStyle(DefaultTabViewStyle())
        .onAppear {
            if let user = Auth.auth().currentUser{
                gd.user_name = user.displayName ?? ""
                print("AppView name:\(gd.user_name)")
            }
        }
    }
}

2. 为FullScreenCover中的AppView传递EnvironmentObject

在ContentView的登录按钮全屏跳转中,必须传递已有的gd和data实例,否则新打开的AppView会找不到对应对象:

.fullScreenCover(isPresented: $showBool){
    AppView()
        .environmentObject(data)
        .environmentObject(gd)
}

3. 移除冗余的EnvironmentObject注入

AppView的body中无需重复添加.environmentObject(data)和.environmentObject(gd),这些对象会从父视图自动继承,重复添加反而容易造成混淆。

内容的提问来源于stack exchange,提问作者eileen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 14:24:56