我正在尝试读取Firestore文档的值。我尝试了两种不同的方法,但是每种方法都失败了。在第一个中,在返回行上引发错误Unexpected non- void return value in void function。我发现了发生这种情况的原因,因此,我实现了第二种方法。
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语句后不久。是否因为它是异步需求?如果是这样,我应该如何解决呢?
UserInformationDocument(dictionary: document.data()!)?.lists!
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调用是一个异步函数。由于它正在与服务器通信(如您所述),因此需要花费额外的时间来执行- 结果,完成块(在您的示例中定义document并err在您的示例中定义的块)发生在主体其余部分之外的不同时间功能的 这意味着您不能从其内部 返回 值,但可以将另一个闭包传递给它,以便稍后执行。这称为 完成块 。
document
err
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 } })