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

使用FirebaseFirestore与SwiftData时Codable解码错误求助

问题分析与解决方案

错误核心原因

你遇到的valueNotFound报错主要由两个问题导致:

  1. 获取了空文档:getBookData方法里的db.collection("Books").document()会创建一个全新的空文档引用,调用getDocument后返回的是不存在的空数据,解码时自然找不到键值容器。
  2. CodingKeys命名不规范:虽然CodingKeys5能正常工作,但不符合Swift常规命名约定,可能引发潜在解析混淆(非本次报错直接原因)。

修复步骤

1. 修正Firestore文档获取逻辑

要获取实际存在的文档,必须指定文档ID,或者查询整个集合的文档:

  • 获取单个指定文档:
func getBookData() async throws -> Books {
    let db = Firestore.firestore()
    // 替换为你Firestore中实际存在的文档ID,比如"sample-book"
    let targetDoc = db.collection("Books").document("your-existing-document-id")
    let book = try await targetDoc.getDocument(as: Books.self)
    return book
}
  • 获取集合中所有文档:
func getAllBooks() async throws -> [Books] {
    let db = Firestore.firestore()
    let querySnapshot = try await db.collection("Books").getDocuments()
    return querySnapshot.documents.compactMap { try? $0.data(as: Books.self) }
}

2. 规范CodingKeys命名

将CodingKeys5重命名为标准的CodingKeys,符合Swift编码习惯:

@Model
class Books: Codable {
    enum CodingKeys: CodingKey {
        case name, pages
    }
    
    var name: String
    var pages: Int
     
    init(
        name: String,
        pages: Int = 0
    ) {
        self.name = name
        self.pages = pages
    }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try container.decode(String.self, forKey: .name)
        self.pages = try container.decode(Int.self, forKey: .pages)
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(name, forKey: .name)
        try container.encode(pages, forKey: .pages)
    }
}

3. 增加文档存在性校验

避免因文档不存在导致的解码错误,可在解码前判断文档状态:

func getBookData() async throws -> Books {
    let db = Firestore.firestore()
    let targetDoc = db.collection("Books").document("your-document-id")
    let snapshot = try await targetDoc.getDocument()
    
    guard snapshot.exists else {
        throw NSError(domain: "FirestoreError", code: 404, userInfo: [NSLocalizedDescriptionKey: "目标文档不存在"])
    }
    
    let book = try snapshot.data(as: Books.self)
    return book
}

额外注意事项

  • 确保Firestore中Books集合下的文档字段名,与CodingKeys定义的name、pages完全一致(大小写敏感)。
  • SwiftData的@Model类结合Codable时,不要添加未纳入编码逻辑的额外属性,否则会触发解码失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 17:25:06