что-то идет не так при попытке обновить строки таблицы после удаления данных 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, но таблица обновляется странным образом, добавляя новые строки ниже существующих.
Я предполагаю, что где-то еще в вашем приложении есть код вроде action .observe(.value
, который показывает данные в виде таблицы. Когда вы удаляете узел из базы данных, код, который заполняет базу данных, снова запускается и снова добавляет те же данные (за исключением узла, который вы удалили) в табличное представление.
При работе с Firebase лучше всего следовать принципу разделение ответственности командных запросов, что означает, что код, который изменяет данные, полностью отделен от потока, который отображает данные. Это означает, что ваш код, который удаляет данные, не должен пытаться обновить табличное представление. Итак, что-то вроде:
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
на их основе. Это больше работы в вашем коде, но приведет к более плавному пользовательскому интерфейсу, когда есть много сообщений.Спасибо, Фрэнк. Просто добавил self.messages.removeAll()
перед строкой child.removeValue
и self.tableView.reloadData()
с DispatchQueue.main.async
после и, кажется, начал работать правильно
Не могу понять, что не так, и я был бы признателен за любой совет или решение.