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

Firebase获取用户分类异常:空结果及Codable解码失败问题

问题:Firebase获取用户分类数据为空/解码失败

我正在开发一款以Firebase为数据库的应用,尝试获取用户的分类数据。Firebase控制台显示用户注册时默认添加了3个分类,但调用接口始终返回空结果。我试过调试,还把调用代码移到.onAppear方法里,都没解决问题。

Firebase控制台截图:
Firebase控制台截图


初始代码实现

Firebase Manager类中获取分类的代码

func fetchCategories(forUserId userId: String, completion: @escaping (Result<[Category], Error>) -> Void) {
        
        let categoriesRef = db.collection("users").document(userId).collection("categories")
        print("user id: \(userId)")
        categoriesRef.getDocuments { (snapshot, error) in
            if let error = error {
                completion(.failure(error))
                return
            }

            guard let documents = snapshot?.documents else {
                completion(.failure(FirestoreErrorCode.notFound as! Error))
     
                return
            }

            let categories = documents.compactMap { document -> Category? in
                do {
                    return try document.data(as: Category.self)
                } catch {
                    print("Error decoding category: \(error)")
                    return nil
                }
            }

            completion(.success(categories))
        }
    }

调用代码

.onAppear {
                FirebaseManager().fetchCategories(forUserId: Auth.auth().currentUser?.uid ?? "") { result in
                    do {
                        let categories = try result.get()
                        print("fetched categories")
                        print(categories.isEmpty ? categories : categories[0])
                        if categories.isEmpty == false {
                            firstCategory = categories[0]
                        }
                    } catch {
                        print("Error fetching categories: \(error.localizedDescription)")
                    }
                    
                }
            }

更新1:改用@EnvironmentObject管理分类数据

根据建议,我在FirebaseManager类里实现了categories数组:

private var db = Firestore.firestore()

@Published var categories: [Category] = []

init() {
    if let userID = Auth.auth().currentUser?.uid {
        fetchCategories(userID: userID)
    }
}

同时修改了获取分类的函数:

func fetchCategories(userID: String) {
    let docRef = db.collection("categories").document(userID)
    docRef.getDocument { (document, error) in
        guard error == nil else {
            print("error", error?.localizedDescription ?? "")
            return
        }
        
        if let document = document, document.exists {
            let data = document.data()
            if let data = data {
                print("data", data)
                self.categories = data["categories"] as? [Category] ?? []
                print(self.categories)
            }
        }
        
    }
}

此外,我通过FirebaseManager类的@EnvironmentObject访问categories数组:

@EnvironmentObject var firebaseManager: FirebaseManager

var categories: [Category] {
    var categories = firebaseManager.categories
    print(categories)
    return categories
}

并且在@main App声明中添加了@StateObject,并将其注入到WindowGroup的首个视图:

WindowGroup {
        ZStack {
            if Auth.auth().currentUser != nil {
                let _ = print("content view triggered when loading app")
                ContentView()
                    .environmentObject(firebaseManager)
                    .environmentObject(userData)
            } else {
                let _ = print("welcome view triggered when loading app")
                WelcomeScreen()
                    .environment(firebaseManager)
                    .environmentObject(userData)  
            }
        }
    }

但问题仍未解决...


更新2:数据获取成功,但解码失败

我已成功从Firebase获取到数据,但现在无法将数据解码为Category类型。

修改后的获取函数:

func fetchCategories(userID: String) {
    let docRef = db.collection("users").document(userID)
    docRef.getDocument { (document, error) in
        guard error == nil else {
            print("error", error?.localizedDescription ?? "")
            return
        }
        
        if let document = document, document.exists {
            let data = document.data()
            if let data = data {
                print("data", data)
                //self.categories = data["categories"] as? [Category] ?? []
                self.categories.append(contentsOf: data["categories"] as? [Category] ?? [Category(title: "Category", emoji: "📚", items: [
                    Item(title: "ToDo Nr.1", emoji: "📚", priority: .high)
                    ])])
            }
        } else {
            print("no document exists")
        }
        
    }
}

我已为Category类型实现了Codable协议,但不确定如何应用到Firebase返回的数据:

func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(id, forKey: .id)
    try container.encode(title, forKey: .title)
    try container.encode(emoji, forKey: .emoji)
    try container.encode(items, forKey: .items)
}

required init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    id = try container.decodeIfPresent(String.self, forKey: .id)
    title = try container.decode(String.self, forKey: .title)
    emoji = try container.decode(String.self, forKey: .emoji)
    items = try container.decode([Item].self, forKey: .items)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 13:48:10