将Firestore文档的值分配给变量 [英] Assign value of a Firestore document to a variable
问题描述
我正在尝试读取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!
分配给变量,然后在函数末尾返回该变量(请参见下面的代码).但是,当我这样做时,该函数将返回一个空数组.让我惊讶的是,打印返回了正确的值,但是在函数执行了return语句后不久.是否因为它是异步需求?如果是这样,我应该如何解决呢?
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调用是一个异步函数.由于它正在与服务器通信(如您所述),因此需要花费额外的时间来执行-结果,完成块(在示例中定义document
和err
的块)发生在外部的不同时间该功能的其余部分.这意味着您不能从其内部返回一个值,但可以将另一个闭包传递给它,以便稍后执行.这称为补全块.
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屋!