Ad

Firebase & GeoFire Fetch Double Adds New Post To Collection View

getting double posts in my Posts array when adding new posts. resulting in 2 identical new posts in my collection view

Im running Firebase realtime database, with geoFire for location based queries. i'm adding posts to 'posts' and location data to 'post_locatons'. now posting works perfectly, not problems at all. and loading the app for the first time, my collection view data fetches and loads perfectly.

only when i add a new post and then refetch data and reload my collectionView, does it double add the new post to my posts = Post array. and it's only the new/last item. so instead of posts.count being a total of 10 with the new post, i get 11, the last 2 being the same thing. my collection view reloads i get 2 identical new posts.

func refreshCollectionView() {
    self.collectionView.reloadData()
}

func fetchPosts(handleComplete:@escaping (()->())) {
    self.posts.removeAll()
    guard  let curLat = liveSavedPlace?.coordinate.latitude else { return }
    guard let curLong = liveSavedPlace?.coordinate.longitude else { return }
    let myLocation = CLLocation(latitude: curLat, longitude: curLong)

    let ref = Database.database().reference()
    let geofireRef = ref.child("posts_location")
    let geoFire = GeoFire(firebaseRef: geofireRef)

    let circleQuery = geoFire.query(at: myLocation, withRadius: 10)

    circleQuery.observe(.keyEntered, with: { key, location in

        POSTS_REF.child(key).observeSingleEvent(of: .value) { (snapshot) in
            guard let dictionary = snapshot.value as? Dictionary<String, AnyObject> else { return }
            let post = Post(postId: key, dictionary: dictionary)
            self.posts.append(post)
            handleComplete()
        }

    })
}

like i said, on viewDidLoad, everything works perfectly, also the DB saves everything perfectly, there are no double posts and no double locations.. only when i post a new and come back to my collection view , fetchPosts runs again and everything is good until the last 2 where it adds another Post to posts thats a double of my new post.

and fyi, posts is never touched from my new Posting functionality, it's all done on my collectionView controller.

i've been trying to figure out where this extra post is coming from, but no dice

ANSWERED i got this fixed, i posted how i fixed it below as an answer if anyone is looking to do something similar

Ad

Answer

When you call circleQuery.observe(.keyEntered, it starts an observer. This will continue to observe for keys entering the queried range, until you remove the observer. Since you never remove the observer, the second time you call fetchPosts you're actually adding a second observer, and that means your code will be called twice for each key that is in range.

define the handle and query in your class so you can then access it outside of the fetchPosts function

var handle: DatabaseHandle!
var circleQuery: GFCircleQuery!

To remove the observer, make sure you keep the handle that is returned when you attach the observer:

circleQuery = geoFire.query(at: myLocation, withRadius: 10)

self.handle = circleQuery?.observe(.keyEntered, with: { key, location in

And then remove the observer by calling in fetchPosts completion Handler:

func refreshCollectionView() {
    circleQuery?.removeObserver(withFirebaseHandle: handle)
    self.collectionView.reloadData()
}

If you're only looking for objects in the range of the query when you call fetchPosts and don't want to keep observing, you'll typically remove the observer once GeoFire has called you for all initial objects, which is when it is 'ready' with the query:

circleQuery.observeReadyWithBlock({
  print("All initial data has been loaded and events have been fired!")
  circleQuery.removeObserverWithHandle(handle)
})
Ad
source: stackoverflow.com
Ad