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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 21:15:05