一尘不染

将Firestore文档的值分配给变量

swift

我正在尝试读取Firestore文档的值。我尝试了两种不同的方法,但是每种方法都失败了。在第一个中,在返回行上引发错误Unexpected non- void return value in void function。我发现了发生这种情况的原因,因此,我实现了第二种方法。

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!给变量,然后在函数末尾返回该变量(请参见下面的代码)。但是,当我这样做时,该函数将返回一个空数组。让我惊讶的是,打印返回了正确的值,但是在函数执行了return语句后不久。是否因为它是异步需求?如果是这样,我应该如何解决呢?

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
}

阅读 173

收藏
2020-07-07

共1个答案

一尘不染

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

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)
        }
    }
}

然后,您可以这样在代码的其他位置调用此函数:

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
    }
})
2020-07-07