我正在尝试读取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
}
答案 0 :(得分:1)
Firebase调用是一个异步函数。由于它正在与服务器通信(如您所述),因此需要花费额外的时间执行-结果,完成块(在您的示例中定义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
}
})