使用FirebaseFirestore与SwiftData时Codable解码错误求助
问题分析与解决方案
错误核心原因
你遇到的valueNotFound报错主要由两个问题导致:
- 获取了空文档:
getBookData方法里的db.collection("Books").document()会创建一个全新的空文档引用,调用getDocument后返回的是不存在的空数据,解码时自然找不到键值容器。 - 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
相关产品推荐
相关产品推荐

