在删除 Firebase 数据后尝试更新 TableView 的行时出现问题。
下面是我使用的方法。
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .destructive, title: "Delete") { (action, indexPath) in
let cell = self.messages[indexPath.row]
let b = cell.msgNo
let action = MyGlobalVariables.refMessages.child(MyGlobalVariables.uidUser!)
action.queryOrdered(byChild: "msgNo").queryEqual(toValue: b).observe(.childAdded, with: { snapshot in
if snapshot.exists() { let a = snapshot.value as? [String: AnyObject]
let autoId = a?["autoID"]
action.child(autoId as! String).removeValue()
self.messages.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
} else {
print("snapshot empty")
}}) }
...
return [delete, edit, preview]
}
最初我检查了整个逻辑,不包括 /*action.child(autoId as!String).removeValue()*/
行,然后它正常工作并按应有的方式删除行。但是一旦我添加了这一行,它就会从 Firebase 中删除数据,但是 tableview 会通过在现有
最佳答案
我的猜测是您的应用程序中的其他地方有类似 action .observe(.value
的代码,它在 TableView 中显示数据。当您从数据库中删除节点时,代码填充数据库的数据再次被触发,它再次将相同的数据(减去您删除的节点)添加到 TableView 。
使用 Firebase 时,最好遵循 command query responsibility segregation原则,这意味着您将修改数据的代码与显示数据的流程完全分开。这意味着您删除数据的代码不应尝试更新 TableView 。所以更像是:
let action = MyGlobalVariables.refMessages.child(MyGlobalVariables.uidUser!)
action.queryOrdered(byChild: "msgNo").queryEqual(toValue: b).observe(.childAdded, with: { snapshot in
if snapshot.exists() { let a = snapshot.value as? [String: AnyObject]
let autoId = a?["autoID"]
action.child(autoId as! String).removeValue()
} else {
print("snapshot empty")
}}) }
以上所做的只是从数据库中删除选定的消息。
现在您可以专注于您的观察者,并确保它只显示一次消息。有两种选择:
- 在您从数据库中添加消息之前,当您的
.value
完成处理程序被调用时,始终清除self.messages
。这是迄今为止最简单的方法,但如果您显示大量数据,可能会导致一些闪烁。 - 收听更细粒度的消息,例如
.childAdded
和.childRemoved
并根据这些消息更新self.messages
。这会在您的代码中增加工作量,但会在消息较多时产生更流畅的 UI。
关于swift - 删除 Firebase 数据时遇到更新 TableView 行的麻烦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56325915/