从 Firebase 检索数据以在表格视图中显示数据时出现并发问题



我目前正在尝试从 Swift 中的实时数据库 (Firebase( 中检索用户数据,并在表格视图中显示用户名。 我有以下函数从位于文件主类中的数据库中检索所有用户(我附加到的变量用户之前已经作为空字符串数组启动(。

func retrieveAllUsers(){
//hold all users
var userFullName = ""
self.usersReference.observeSingleEvent(of: .value, with: {(snapshot) in
// if marker ID has children it means this marker has already been created
//go in User ID uid
if snapshot.hasChildren() {
// go through all user ids
for child in snapshot.children {
//initialize a user name and first name
var userFirstName = ""
var userLastName = ""
let subSnap = child as! DataSnapshot
//get child key with format UserID: uid
let key = subSnap.key
// go inside User ID to retrieve name and first name of every user
DispatchQueue.main.async {
self.usersReference.child(key).observeSingleEvent(of: .value, with: { (snapshot2) in
// go through user parammters to only retrieve his name and first name
for grandChild in snapshot2.children {
let nameGatherer = grandChild as! DataSnapshot
if nameGatherer.key == "First Name:"{
userFirstName = nameGatherer.value as! String
}
if nameGatherer.key == "Last Name:"{
userLastName = nameGatherer.value as! String
}
}//end of loop inside user parameters
//add his full name to the list of users which we will then filter later on
userFullName = userFirstName + userLastName
self.users.append(userFullName)
self.tableView.reloadData()
print("IN CLOSURE: (self.users)")
})// end of observation of one user parameters
}//end of dispatch async
print("OUTSIDE CLOSURE1: (self.users)")
}//end of looking inside the user ID node
print("OUTSIDE CLOSURE2: (self.users)")
}//end of if there are users children
print("OUTSIDE CLOSURE3: (self.users)")
})//end of observation of users reference
print("OUTSIDE CLOSURE4: (self.users)")
}

在我看来,我有

retrieveAllUsers()
print("USERS:(self.users)")
tableView.reloadData()

我尝试使用并发与 Dispatchmain.async (这是我第一次在我的程序中做并发(。然而,它似乎不起作用,因为我的视图DidLoad 中的打印首先出现并且用户为空,因此它没有显示在我的表视图中,并且打印 ** print("OUT CLOSURE1:(self.users("(** 与包含正确用户信息的数组一起排在最后。

谁能帮我获取要在表视图中显示的正确用户信息?我真的很感激。 非常感谢! 安东尼

您的问题之所以是原因造成的,是因为您对self.tableView.reloadData()的调用实际上是在包含您的数据的 Firebase 回传中。不保证此回调位于主线程上,并且所有 UI 操作必须始终在主线程上进行。您需要包装调用以直接DispatchQueue.main.async内部重新加载表(而不是嵌套在另一个调用中(,以确保在主线程上调用它。

您也不需要在DispatchQueue.main.async中调用嵌套调用。看我的例子:

func retrieveAllUsers(){
//hold all users
var userFullName = ""
self.usersReference.observeSingleEvent(of: .value, with: {(snapshot) in
// if marker ID has children it means this marker has already been created
//go in User ID uid
if snapshot.hasChildren() {
// go through all user ids
for child in snapshot.children {
//initialize a user name and first name
var userFirstName = ""
var userLastName = ""
let subSnap = child as! DataSnapshot
//get child key with format UserID: uid
let key = subSnap.key
// go inside User ID to retrieve name and first name of every user
self.usersReference.child(key).observeSingleEvent(of: .value, with: { (snapshot2) in
// go through user parammters to only retrieve his name and first name
for grandChild in snapshot2.children {
let nameGatherer = grandChild as! DataSnapshot
if nameGatherer.key == "First Name:"{
userFirstName = nameGatherer.value as! String
}
if nameGatherer.key == "Last Name:"{
userLastName = nameGatherer.value as! String
}
}//end of loop inside user parameters
//add his full name to the list of users which we will then filter later on
userFullName = userFirstName + userLastName
self.users.append(userFullName)
DispatchQueue.main.async {
self.tableView.reloadData()
}
print("IN CLOSURE: (self.users)")
})// end of observation of one user parameters
print("OUTSIDE CLOSURE1: (self.users)")
}//end of looking inside the user ID node
print("OUTSIDE CLOSURE2: (self.users)")
}//end of if there are users children
print("OUTSIDE CLOSURE3: (self.users)")
})//end of observation of users reference
print("OUTSIDE CLOSURE4: (self.users)")
}

最新更新