Swift中如何从Firestore读取多个自定义对象?
解决Swift Firestore读取多个自定义对象的解码错误
你猜的完全没错!单文档查询返回的DocumentSnapshot和多文档查询结果里的QueryDocumentSnapshot确实是不同类型,这就是你遇到Value of type 'QueryDocumentSnapshot' has no member 'flatMap'错误的核心原因。
为什么会有这个差异?
- 单文档查询(
getDocument)返回的DocumentSnapshot是可选的——目标文档可能不存在(比如被删除了),所以需要用flatMap处理“文档不存在”的可选情况。 - 多文档查询返回的
QueryDocumentSnapshot则代表肯定存在的文档——能出现在查询结果里的都是Firestore中实际存在的文档,因此它没有flatMap方法,也不需要处理“文档不存在”的场景。
修正后的代码示例
基础循环解码版本
直接遍历查询结果中的每个QueryDocumentSnapshot,调用data(as:)方法解码即可:
db.collection("cities").whereField("capital", isEqualTo: true) .getDocuments() { (querySnapshot, err) in if let err = err { print("Error getting documents: \(err)") return } guard let snapshotDocuments = querySnapshot?.documents else { print("No documents found matching the query") return } for document in snapshotDocuments { do { // QueryDocumentSnapshot的data(as:)直接返回非可选的City(因为文档肯定存在) let city = try document.data(as: City.self) print("Decoded city: \(city)") } catch { // 处理单个文档解码失败的情况 print("Failed to decode city with ID \(document.documentID): \(error)") } } }
批量转数组版本(更实用)
如果需要把所有解码成功的对象整理成数组,可以用compactMap批量处理,同时忽略解码失败的项:
db.collection("cities").whereField("capital", isEqualTo: true) .getDocuments() { (querySnapshot, err) in if let err = err { print("Error getting documents: \(err)") return } guard let snapshotDocuments = querySnapshot?.documents else { print("No documents found matching the query") return } // 批量解码为City数组,自动过滤解码失败的文档 let capitalCities: [City] = snapshotDocuments.compactMap { document in do { return try document.data(as: City.self) } catch { print("Skipping invalid city document \(document.documentID): \(error)") return nil } } print("Successfully loaded \(capitalCities.count) capital cities:") capitalCities.forEach { city in print("- \(city.name) (Country: \(city.country))") } }
关键注意点
QueryDocumentSnapshot的data(as:)方法会直接抛出错误(比如解码失败),但不会返回可选值,因为文档本身一定存在。- 如果你的
City模型需要自定义解码逻辑,确保它遵循FirestoreDecodable(或Codable并正确配置Firestore编码/解码规则)。
内容的提问来源于stack exchange,提问作者Stormwaker
相关产品推荐
相关产品推荐

