Reputation: 1661
I have a UICollectionViewController
which acts as a feed that retrieves and displays data from my Firebase database. It's the window's root view controller, so it always exists. My issue is that every time the controller appears, all of the children from its observed node get added to the collection view. This is fine initially, but when I leave the controller and return, all of the same data gets appended, creating duplicates. Here is some pseudo-code, representing my interaction with Firebase:
class ViewController: UIViewController {
var children_query: DatabaseQuery!
override func viewDidLoad() {
super.viewDidLoad()
self.children_query = Database.database().reference().child("children").queryOrdered(byChild: "timestamp").queryStarting(atValue: Date().timeIntervalSince1970)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.observeAddedChildren()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.children_query.removeAllObservers()
}
func observeAddedChildren() {
self.children_query.observe(.childAdded, with: { snapshot in
print(snapshot.value)
})
}
}
In this pseudo-code, instead of dealing with UI, I simply print snapshot
, but the point remains. All of the children get printed each time the controller appears. How can I retrieve only data that hasn't been retrieved? Thanks.
Upvotes: 0
Views: 1145
Reputation:
I haven't used Firebase, but when you pass a block to the observe
function, there's nothing to suggest the observation stops when the view disappears.
So I wonder if calling observe
multiple times is the problem. Have you tried calling observe
just once, in ViewDidLoad?
Alternatively, have a property to record whether the observation has been started:
var observing: Bool = false
func observeAddedChildren() {
if observing {
return false
}
self.children_query.observe(.childAdded, with: { snapshot in
print(snapshot.value)
})
observing = true
}
Edit: here's a couple more ways, because you're presumably adding the snapshot
items to an array or other collection, then your UICollectionViewDataSource
is reading stuff from that array.
So either:
viewWillAppear
and then call self.collectionView.reloadData()
, orsnapshot
object has a unique identifier property, then put this into an array, and then the observe block can ignore items it's already seen beforeLike this:
var snapshotIDs : [String] = Array<String>()
func observeAddedChildren() {
self.children_query.observe(.childAdded, with: { snapshot in
if !snapshotIDs.contains(snapshot.uniqueID) {
print(snapshot.value)
snapshotIDs.append(snapshot.uniqueID)
}
})
}
Upvotes: 1