Вместо длинного обсуждения в комментариях давайте попробуем ответить на это парой ссылок и примером кода.
Во-первых, синхронизировать данные следует только тогда, когда представление является видимым и вызывается метод viewWillAppear.каждый раз вид становится видимым, так что это хорошее место для добавления наблюдателей.Также хорошей практикой является удаление наблюдателей, когда они вам не нужны (экономит пропускную способность), и это можно сделать с помощью маркера firebase в viewDidDisappear.Вот немного устаревшая статья, но отличное чтение
Лучшие практики для UIViewController и Firebase
и отличный пример, см. Ответ на этот вопрос
Firebase: когда вызывать removeObserverWithHandle в swift
Для решения остальной части вопроса (обратите внимание, я держу это сокращение, поэтому я не включил использование ручек)
У меня есть класс для хранения предупреждений
class AlertClass {
var node_key = ""
var msg = ""
init(aKey: String, aMsg: String) {
self.node_key = aKey
self.msg = aMsg
}
}
, а затем массив var класса для хранения всех предупреждений
var alertArray = [AlertClass]()
, а затем мы добавляем наших наблюдателей из функции viewWillAppear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.addObservers()
}
, который добавляет трех наблюдателей к указанному узлу;.childAdded, .childChanged и .childRemoved.Имейте в виду, что .childAdded будет перебирать узлы в узле ref и заполнять наш источник данных каждый раз, когда вызывается viewWillAppear, поэтому нам нужно «сбросить» массив, чтобы мы случайно не загрузили данные поверх существующих данных.Ваш вариант использования может отличаться, поэтому используйте соответствующий код.
Вот код для добавления наблюдателей и печати массива в любое время, когда есть изменение.
func addObservers() {
let ref = self.ref.child("Continent").child("Europe").child("Country").child("Italy").child("Region").child("Emilia-Romagna").child("City").child("Bologna").child("Community").child("Alert Notifications")
self.alertArray = []
ref.observe(.childAdded, with: { (snapshot) in
let key = snapshot.key
let msg = snapshot.childSnapshot(forPath: "msg").value as! String
let aAlert = AlertClass(aKey: key, aMsg: msg)
self.alertArray.append(aAlert) //append the new alert
self.showAlertArray() //this is called for every child
})
ref.observe(.childChanged, with: { (snapshot) in
let key = snapshot.key
let msg = snapshot.childSnapshot(forPath: "msg").value as! String
if let foundAlert = self.alertArray.first(where: { $0.node_key == key } ) {
foundAlert.msg = msg //update the alert msg
self.showAlertArray()
}
})
ref.observe(.childRemoved, with: { (snapshot) in
let key = snapshot.key
self.alertArray.removeAll(where: { $0.node_key == key }) //remove the alert
self.showAlertArray()
})
}
func showAlertArray() {
for alert in self.alertArray {
print(alert.node_key, alert.msg)
}
}
и в качестве примечания ...
Если вы заполняете источник данных tableView через childAdded, вам может быть интересно, как это сделать без повторного вызова tableView.reloadData, что может вызвать мерцание.Есть способ сделать это, используя тот факт, что события .value вызываются после .childAdded.См. Мой ответ на этот вопрос для примера.