我在类文件中声明了一个字典,如下所示:
var myDict: [Int: String] = [:]
我还创建了一个更改字典中值的函数:
func firebaseToDictionary() {
let uid = FIRAuth.auth()?.currentUser?.uid
let infoRef = FIRDatabase.database().reference().child("users").child(uid!).child("info")
infoRef.observe(FIRDataEventType.value, with: { (snapshot) in
let postDict = snapshot.value as? [String: String]
for item in postDict! {
let theString = item.value["FirebaseString"]
let theNumber = item.value["FirebaseInt"]
self.myDict[theNumber] = theString
//First Print
print(myDict)
}
})
//Second Print
print(myDict)
}
在//First Print
,字典包含新值并且看起来很好,但是//Second Print
显示了创建的字典;为[:]
。 //Second Print
实际显示在//First Print
为什么我的字典仍然显示为[:],即使我在函数内部更改了它?
答案 0 :(得分:1)
从您的代码看来infoRef.observe()
似乎是一个异步任务,因此如果您之后有一个代码,它可能会在异步任务执行之前执行。您可以按如下方式更改代码:
func firebaseToDictionary() {
let uid = FIRAuth.auth()?.currentUser?.uid
let infoRef = FIRDatabase.database().reference().child("users").child(uid!).child("info")
infoRef.observe(FIRDataEventType.value, with: { (snapshot) in
let postDict = snapshot.value as? [String: String]
for item in postDict! {
let theString = item.value["FirebaseString"]
let theNumber = item.value["FirebaseInt"]
self.myDict[theNumber] = theString
//First Print
print(myDict)
DispatchQueue.main.async {
tableView.reloadData()
}
}
})
}
观察后添加的任何内容都可以立即执行,而无需等待观察部分完成。因此,请确保在完成之后是否要执行某些操作,请在块内执行。
答案 1 :(得分:1)
您的代码工作正确。你有一个同步函数,它在后台线程中获取数据
infoRef.observe(FIRDataEventType.value, with: { (snapshot) in
let postDict = snapshot.value as? [String: String]
for item in postDict! {
let theString = item.value["FirebaseString"]
let theNumber = item.value["FirebaseInt"]
self.myDict[theNumber] = theString
//First Print
print(myDict)
}
})
从远程数据库接收数据后,将调用此闭包内的代码。因此,如果您在此异步调用之后有另一个print(myDict)
,它将首先打印出来,其中包含原始值。然后,当异步调用完成并且闭包内的代码被执行时,第一个print(myDict)
被触发,然后使用新更新的数据
话虽这么说,你的新数组在回调你的闭包之前没有加载数据。从您的代码中,您似乎有一个显示此数组的数据库的表视图。所以你必须等到数组获取数据然后重新加载表视图。所以你需要将代码带到闭包的末尾。但是,在swift中,您无法直接从后端线程更新UIElement,就像这个回调函数一样。因此,在填充数组之后,需要以这种方式在主线程中运行表视图重新加载代码
infoRef.observe(FIRDataEventType.value, with: { (snapshot) in
let postDict = snapshot.value as? [String: String]
for item in postDict! {
let theString = item.value["FirebaseString"]
let theNumber = item.value["FirebaseInt"]
self.myDict[theNumber] = theString
//First Print
print(myDict)
DispatchQueue.main.async {
tableView.reloadData()
}
}
})