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

使用Codable从FireStore读取自定义数据类型时遇数据丢失问题

问题描述

我正在用Codable从Firebase FireStore读取自定义数据类型(map),这是低开销的数据检索方式。只用GBplayer结构体时脚本正常运行,能在SwiftUI视图里获取完整列表,但添加shotAverages结构体后,Firestore文档里包含该字段的玩家会从列表中消失,无法被检索到。

数据模型

struct GBplayer: Identifiable, Codable {
    @DocumentID var id: String? = UUID().uuidString
    var name: String
    var status: String
    var age: String
    var height: String
    var college: String
    var team: String
    var position: String
    var shootingAverages: shotAverages?
}

struct shotAverages: Identifiable, Codable {
    @DocumentID var id: String? = UUID().uuidString
    var aveTWOperc: Double
    var aveTHREEperc: Double
    var aveFTperc: Double
    var aveeFGperc: Double
}

数据视图模型

class GBplayerModel: ObservableObject {

    @Published var playerList = [GBplayer]()
    
    // 获取数据库引用
    let db = Firestore.firestore()

    func getGBplayers() {
        db.collection("GBplayers").addSnapshotListener { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("没有找到文档")
                return
            }
           
            self.playerList = documents.compactMap { (queryDocumentSnapshot) -> GBplayer? in
                return try? queryDocumentSnapshot.data(as: GBplayer.self)
            }
        }
    }
}

Firestore数据结构参考截图:
Firestore文档截图


问题排查与解决

核心原因

shotAverages结构体中的@DocumentID注解是问题根源。@DocumentID是Firebase用来映射独立文档ID的属性包装器,但shotAverages只是Firestore文档里的嵌套map字段,并不是独立文档,不存在对应的文档ID。Codable解析时找不到这个ID字段,会导致整个GBplayer对象解析失败,被compactMap过滤掉,所以带该字段的玩家从列表中消失。

修复方案

  1. 移除shotAverages里的@DocumentID属性,嵌套map不需要文档ID;
  2. 遵循Swift命名规范,结构体首字母大写(改为ShotAverages),避免风格不一致引发潜在问题。

修改后的代码:

// 修正后的嵌套结构体
struct ShotAverages: Codable {
    var aveTWOperc: Double
    var aveTHREEperc: Double
    var aveFTperc: Double
    var aveeFGperc: Double
}

// 更新GBplayer中的字段类型
struct GBplayer: Identifiable, Codable {
    @DocumentID var id: String? = UUID().uuidString
    var name: String
    var status: String
    var age: String
    var height: String
    var college: String
    var team: String
    var position: String
    var shootingAverages: ShotAverages?
}

额外注意事项

  • 确认Firestore中嵌套map的字段名和结构体属性名完全匹配(大小写敏感),比如截图中的aveeFGperc要和代码里的属性名一致;
  • 保持shootingAverages为可选类型是正确的,这样没有该字段的文档也能正常解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 16:22:49