Firestore文档单值提取问题:无法返回可用字段值
从Firebase Firestore获取单个字段值的问题
问题1:异步方法无法返回字段值
我现在能通过CoreInfCall传入字符串,把Firestore文档里对应字段的值打印到终端,但没法以程序可用的形式返回这个值。试了把print换成return、赋值给变量再返回都没用,代码如下:
func fetchU_CoreInf_X (CoreInfCall: String) { let uid = FirebaseManager.shared.auth.currentUser?.uid let ref = FirebaseManager.shared.firestore.collection("Users").document(uid!).collection("colCoreInfo").document("docCoreInfo") ref.getDocument { (snapshot, error) in if let documents = snapshot?.data() { print(documents["\(CoreInfCall)"]!) } else { print("No Documents") } } }
我只想提取单个键值对,不想遍历所有键值对,但不知道怎么正确返回这个值。
问题2:调用.get方法报错
后来试了用.get方法直接获取字段,结果报错:Value of type 'DocumentReference' has no member 'get',已经导入了Firebase和FirebaseFirestore,代码如下:
func GetPet() -> String { let uid = FirebaseManager.shared.auth.currentUser?.uid var db = Firestore.firestore() var HvPetout = db.collection("Users") .document(uid).collection("colHobbies").document("docHobbies").get("inpHvPet") as? String ?? "no HvPetval" return HvPetout as! String }
解决办法
针对问题1:用闭包回调或Async/Await处理异步操作
Firestore的getDocument是异步方法,闭包里的代码会在函数执行完之后才运行,所以直接return或者赋值给外部变量无效。可以用以下两种方式解决:
方式1:闭包回调
修改函数,添加一个完成回调闭包,在获取到值后调用:
func fetchU_CoreInf_X(CoreInfCall: String, completion: @escaping (Any?, Error?) -> Void) { guard let uid = FirebaseManager.shared.auth.currentUser?.uid else { completion(nil, NSError(domain: "AuthError", code: -1, userInfo: [NSLocalizedDescriptionKey: "用户未登录"])) return } let ref = FirebaseManager.shared.firestore.collection("Users") .document(uid) .collection("colCoreInfo") .document("docCoreInfo") ref.getDocument { snapshot, error in if let error = error { completion(nil, error) return } guard let data = snapshot?.data(), let value = data[CoreInfCall] else { completion(nil, NSError(domain: "FirestoreError", code: -1, userInfo: [NSLocalizedDescriptionKey: "未找到对应字段"])) return } completion(value, nil) } } // 使用示例 fetchU_CoreInf_X(CoreInfCall: "你的字段名") { value, error in if let error = error { print("获取失败:\(error.localizedDescription)") return } if let value = value { // 在这里使用获取到的值 print("获取到的值:\(value)") } }
方式2:Async/Await(Swift 5.5+)
如果你的项目支持Swift 5.5及以上,可以用异步函数简化代码:
func fetchU_CoreInf_X(CoreInfCall: String) async throws -> Any { guard let uid = FirebaseManager.shared.auth.currentUser?.uid else { throw NSError(domain: "AuthError", code: -1, userInfo: [NSLocalizedDescriptionKey: "用户未登录"]) } let ref = FirebaseManager.shared.firestore.collection("Users") .document(uid) .collection("colCoreInfo") .document("docCoreInfo") let snapshot = try await ref.getDocument() guard let data = snapshot.data(), let value = data[CoreInfCall] else { throw NSError(domain: "FirestoreError", code: -1, userInfo: [NSLocalizedDescriptionKey: "未找到对应字段"]) } return value } // 使用示例(需要在异步上下文调用) Task { do { let value = try await fetchU_CoreInf_X(CoreInfCall: "你的字段名") print("获取到的值:\(value)") } catch { print("获取失败:\(error.localizedDescription)") } }
针对问题2:修正.get方法的错误用法
DocumentReference没有直接的get(_:)方法,必须先获取文档快照,再从快照的data中提取字段。可以用Async/Await或者闭包的方式实现:
修正后的Async/Await版本:
func getPet() async throws -> String { guard let uid = FirebaseManager.shared.auth.currentUser?.uid else { throw NSError(domain: "AuthError", code: -1, userInfo: [NSLocalizedDescriptionKey: "用户未登录"]) } let ref = Firestore.firestore() .collection("Users") .document(uid) .collection("colHobbies") .document("docHobbies") let snapshot = try await ref.getDocument() guard let value = snapshot.data()?["inpHvPet"] as? String else { return "no HvPetval" } return value } // 使用示例 Task { do { let petValue = try await getPet() print(petValue) } catch { print("获取失败:\(error.localizedDescription)") } }
闭包回调版本:
func getPet(completion: @escaping (String) -> Void) { guard let uid = FirebaseManager.shared.auth.currentUser?.uid else { completion("no HvPetval") return } let ref = Firestore.firestore() .collection("Users") .document(uid) .collection("colHobbies") .document("docHobbies") ref.getDocument { snapshot, error in if let error = error { print("获取失败:\(error.localizedDescription)") completion("no HvPetval") return } let value = snapshot?.data()?["inpHvPet"] as? String ?? "no HvPetval" completion(value) } } // 使用示例 getPet { petValue in print(petValue) }
内容的提问来源于stack exchange,提问作者WPD2050
相关产品推荐
相关产品推荐

