【问题标题】:Firestore getDocument not working properlyFirestore getDocument 无法正常工作
【发布时间】:2020-07-24 15:04:48
【问题描述】:

我正在尝试从我的 Firestore 数据库中获取一个文档,并根据用户的选择过滤返回的数据。如果用户选择["snapchat", "facebook"],那么我试图只从数据库中获取这些特定值。它应该返回["snapchat": username, "instagram": username, "UID": user UID]。但是,当我打印出函数的返回值时,它只包含“UID”的键值。这是我的代码:

func getMediaInfo(selected: [String]) -> Dictionary<String, String> {
    var mediaDict: [String: String] = [:]
    let db = Firestore.firestore()
    let docRef = db.collection("users").document(Auth.auth().currentUser!.uid)
    docRef.getDocument { (document, error) in
        if let document = document, document.exists {
            let dataDescription = document.data()
            for media in selected {
                print(media, ":", dataDescription![media]!)
                mediaDict[media] = (dataDescription![media]! as! String)
            }
        } else {
            print("Document does not exist")
            self.dismiss(animated: true, completion: nil)
        }

    }
    mediaDict["UID"] = Auth.auth().currentUser?.uid
    print("Dictionary: ", mediaDict)
    return mediaDict
}

我的输出是:

Dictionary: ["UID": "ub8bUMYBbeSPXd8UOdJWKCnbQzJ2"]
Twitter : nrjfjfj
Phone Number : nrnrjrn
Snapchat : hello

如您所见,这些值已正确检索和输出。但是,返回的 mediaDict 仅具有“UID”的键值对。似乎该函数在整个字典被填满之前就返回了。我不确定为什么会发生这种情况,也不确定如何解决这个问题。

【问题讨论】:

    标签: ios firebase dictionary google-cloud-firestore


    【解决方案1】:

    数据是从 Firestore(以及大多数现代 Web 和云 API)异步加载的。当你的return mediaDict 运行时,mediaDict[media] = (dataDescription![media]! as! String 还没有被调用,这就是你看不到它的任何内容的原因。

    任何需要数据库数据的代码,都需要在闭包/回调中,或者从那里调用。例如:

    docRef.getDocument { (document, error) in
        var mediaDict: [String: String] = [:]
        mediaDict["UID"] = Auth.auth().currentUser?.uid
        if let document = document, document.exists {
            let dataDescription = document.data()
            for media in selected {
                print(media, ":", dataDescription![media]!)
                mediaDict[media] = (dataDescription![media]! as! String)
            }
        } else {
            print("Document does not exist")
            self.dismiss(animated: true, completion: nil)
        }
        print("Dictionary: ", mediaDict)
    }
    

    您会注意到这里没有return 语句,因为您无法返回尚未加载的内容。


    在闭包/回调中包含代码的替代方法是将您自己的完成处理程序传递给getMediaInfo,并在加载数据后调用它(我们现在有print("Dictionary: ", mediaDict))。

    这看起来像:

    func getMediaInfo(selected: [String], completionHandler: (Dictionary<String, String>) -> ()) {
        let db = Firestore.firestore()
        let docRef = db.collection("users").document(Auth.auth().currentUser!.uid)
        docRef.getDocument { (document, error) in
            var mediaDict: [String: String] = [:]
            mediaDict["UID"] = Auth.auth().currentUser?.uid
            if let document = document, document.exists {
                let dataDescription = document.data()
                for media in selected {
                    print(media, ":", dataDescription![media]!)
                    mediaDict[media] = (dataDescription![media]! as! String)
                }
            } else {
                print("Document does not exist")
                self.dismiss(animated: true, completion: nil)
            }
            completionHandler(mediaDict)
        }
    }
    
    
    getMediaInfo(["one", "two"]) { info in
        print(info)
    }
    

    您会注意到,这与 Firestore API 自身使用的模式非常相似,您只是返回了更特定于应用程序的数据版本。

    另见:

    【讨论】:

    • 谢谢!调用我的函数时,我会在完成处理程序参数中添加什么?我不太确定这些是如何工作的
    • 添加了一个例子。如前所述:它与对getDocument 本身的调用非常相似,它也具有类似的闭包/回调/完成处理程序。因此,当有疑问时,只需根据这些术语搜索类似的示例(这是我刚刚创建链接列表所做的)。
    猜你喜欢
    • 2019-03-13
    • 2020-11-01
    • 2021-07-19
    • 1970-01-01
    • 2021-12-12
    • 2021-09-27
    • 2019-10-17
    • 2016-12-01
    • 2020-09-06
    相关资源
    最近更新 更多