在删除Firebase数据后尝试更新表视图的行时出了点问题。
下面是我使用的方法。
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中删除数据,但是通过在现有
答案 0 :(得分:1)
我的猜测是,应用程序中的其他地方具有类似action .observe(.value
的代码,该代码在表视图中显示数据。当您从数据库中删除节点时,填充数据库的代码将再次被触发,并将相同的数据(减去已删除的节点)再次添加到表视图中。
使用Firebase时,最好遵循command query responsibility segregation原则,这意味着您将修改数据的代码与显示数据的流程完全分开。这意味着删除数据的代码不应尝试更新表视图。所以更像是:
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")
}}) }
以上所有操作是从数据库中删除选定的消息。
现在,您可以专注于观察者,并确保它只显示一次消息。有两种选择:
self.messages
完成处理程序被调用时清除.value
。这是迄今为止最简单的方法,但是如果显示大量数据,可能会导致闪烁。.childAdded
和.childRemoved
,并根据这些消息更新self.messages
。这在您的代码中需要做更多的工作,但是当有许多消息时,将使UI更加平滑。