我有一个函数,该函数应侦听Firebase节点并在发布新帖子时获取它们的快照,但是该功能根本不会让人感到烦恼,好像观察者Bird buzzard = new Bird("Buzzard",
"Buteo buteo",
(short) 51,
(short) 57,
550,
1300,
EnumSet.of(AnimalColour.BROWN)
... // pass in other parameters
);
看不到新帖子一样在节点中发布。我检查了一下,确实在Firebase中实时注册了新帖子。我应该调用该函数还是应该由观察者执行?
继承人的完整功能:
.observe(DataEventType.childAdded, with: { (snapshot) in
非常感谢您。
编辑 重写功能:
func getNewerAlerts(setCompletion: @escaping (Bool) -> ()) {
print(" MapArray.alertNotificationCoordinatesArray before getNewerAlerts snapshot is: \(MapArray.alertNotificationCoordinatesArray)")
print(" self.userAlertNotificationArray before getNewerAlerts snapshot is: \(self.userAlertNotificationArray)")
ref = Database.database().reference()
ref?.child("Continent").child("Europe").child("Country").child("Italy").child("Region").child("Emilia-Romagna").child("City").child("Bologna").child("Community").child("Alert Notifications").observe(DataEventType.childAdded, with: { (snapshot) in
print(" snapshot is: \(snapshot)")
guard let data = snapshot.value as? [String:[String:String]] else { return }
guard let firebaseKey = snapshot.key as? String else { return }
// let date = data!["Date"]
// let time = data!["Time"]
data.values.forEach {
let dataLatitude = $0["Latitude"]!
let dataLongitude = $0["Longitude"]!
let type = $0["Description"]!
let id = Int($0["Id"]!)
let doubledLatitude = Double(dataLatitude)
let doubledLongitude = Double(dataLongitude)
let recombinedCoordinate = CLLocationCoordinate2D(latitude: doubledLatitude!, longitude: doubledLongitude!)
// print("Firebase alerts posts retrieved")
let userAlertAnnotation = UserAlert(type: type, coordinate: recombinedCoordinate, firebaseKey: firebaseKey, title: type,id: id!)
self.mapView.addAnnotation(userAlertAnnotation)
self.userAlertNotificationArray.append(userAlertAnnotation)
MapArray.alertNotificationCoordinatesArray.append(recombinedCoordinate)
}
print(" MapArray.alertNotificationCoordinatesArray after getNewerAlerts snapshot is: \(MapArray.alertNotificationCoordinatesArray)")
print(" self.userAlertNotificationArray after getNewerAlerts snapshot is: \(self.userAlertNotificationArray)")
setCompletion(true)
})
}
答案 0 :(得分:1)
让我们尝试通过几个链接和一个代码示例来回答这个问题,而不是在评论中进行冗长的讨论。
但是,首先,您仅应在视图可见时同步数据,并在每次视图变为可见时调用viewWillAppear方法,因此这是添加观察者的好地方。最好在不需要观察者时删除观察者(节省带宽),并且可以使用viewDidDisappear中的firebase句柄来完成。这是一篇过时的文章,但读得很好
Best Practices for UIViewController and Firebase
并举一个很好的例子,请参阅此问题的答案
Firebase: when to call removeObserverWithHandle in 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时填充我们的dataSource,因此我们需要“重置”数组,以免意外在现有数据之上加载数据。您的用例可能会有所不同,因此请相应编码。
下面是添加观察者并在发生任何更改时打印数组的代码。
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)
}
}
并作为旁注...
如果通过childAdded填充tableView数据源,您可能想知道如何做到这一点,而无需重复调用tableView.reloadData,这可能会导致闪烁。通过利用在.childAdded之后调用.value事件的事实,可以做到这一点。有关示例,请参见我对this question的回答。