将 Firestore 文档的值分配给变量 [英] Assign value of a Firestore document to a variable

查看:29
本文介绍了将 Firestore 文档的值分配给变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试读取 Firestore 文档的值.我尝试过两种不同的方法,但都失败了.在第一个中,返回行抛出错误:Unexpected non-void return value in void function.我发现了为什么会发生这种情况,因此,我采用了第二种方式.

I am trying to read the value of a Firestore document. I have tried doing it two different ways, but each fails. In the first one, an error is thrown on the return line: Unexpected non-void return value in void function. I found out why this happened, and so, I implemented the second way.

import UIKit
import Firestore

func readAvailableLists(forUser user: String) -> [String] {
    let db = Firestore.firestore()
    db.collection("userslist").document(user).getDocument { (document, err) in
        if let document = document, document.exists {
            return UserInformationDocument(dictionary: document.data()!)?.lists!
        } else {
            print("Document does not exist")
        }
    }
}

在第二种方法中,我将 UserInformationDocument(dictionary: document.data()!)?.lists! 分配给一个变量并在函数的末尾返回该变量(见下面的代码).但是,当我这样做时,该函数返回一个空数组.令我惊讶的是,打印返回正确的值,但在函数执行返回语句之后很久.是因为它是异步需求吗?如果是这样,我应该如何解决这个问题?

In the second method, I assign the UserInformationDocument(dictionary: document.data()!)?.lists! to a variable and return that variable at the end of the function (see code below). However, when I do this, it the function returns an empty array. What surprises me is that the print return the correct value, but after long after the function has executed the return statement. Is it because it is an async demand? And if so, how should I fix this?

import UIKit
import Firestore

func readAvailableLists(forUser user: String) -> [String] {
    let db = Firestore.firestore()
    var firestoreUserDocument: [String] = []
    db.collection("userslist").document(user).getDocument { (document, err) in
        if let document = document, document.exists {
            firestoreUserDocument = (UserInformationDocument(dictionary: document.data()!)?.lists!)!
        print((UserInformationDocument(dictionary: document.data()!)?.lists!)!)
        } else {
            print("Document does not exist")
        }
    }
    return firestoreUserDocument
}

推荐答案

Firebase 调用是一个异步函数.执行需要额外的时间,因为它正在与服务器通信(如您所见) - 结果,完成块(定义 documenterr 的块你的例子)发生在不同的时间,在函数体的其余部分之外.这意味着你不能从它内部返回一个值,但是你可以将另一个闭包传递给它,以便稍后执行.这称为完成块.

The Firebase call is an asynchronous function. It takes extra time to execute because it's talking to a server (as you've noted) - as a result, the completion block (the block that defines document and err in your example) happens at a different time, outside of the rest of the body of the function. This means you can't return a value from inside it, but you can pass another closure through to it, to execute later. This is called a completion block.

func readAvailableLists(forUser user: String, completion: @escaping ([String]?, Error?) -> Void) -> [String] {
    let db = Firestore.firestore()
    db.collection("userslist").document(user).getDocument { (document, err) in
        if let document = document, document.exists {
            // We got a document from Firebase. It'd be better to
            // handle the initialization gracefully and report an Error
            // instead of force unwrapping with !
            let strings = (UserInformationDocument(dictionary: document.data()!)?.lists!)!
            completion(strings, nil)
        } else if let error = error {
            // Firebase error ie no internet
            completion(nil, error)
        }
        else { 
            // No error but no document found either
            completion(nil, nil)
        }
    }
}

然后您可以在代码中的其他地方调用此函数,如下所示:

You could then call this function elsewhere in your code as so:

readAvailableLists(forUser: "MyUser", completion: { strings, error in
    if let strings = strings {
        // do stuff with your strings
    }
    else if let error = error {
        // you got an error
    }
})

这篇关于将 Firestore 文档的值分配给变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆