Firebase 和 GeoFire fetch double 添加了新的 post 到 collection 视图

Firebase & GeoFire fetch double adds new post to collection view

在我的 Posts 数组中添加新的 posts 时得到双 posts。在我的 collection 视图

中产生了 2 个相同的新 post

Im 运行 Firebase 实时数据库,使用 geoFire 进行基于位置的查询。我将 posts 添加到 'posts' 并将位置数据添加到 'post_locatons'。现在 posting 工作完美,完全没有问题。并首次加载该应用程序时,我的 collection 视图数据可以完美地获取和加载。

仅当我添加一个新的 post 然后重新获取数据并重新加载我的 collection 视图时,它是否将新的 post 双重添加到我的 posts = Post数组。而且它只是 new/last 项。所以 posts.count 与新 post 的总和不是 10,而是 11,最后 2 个是相同的。我的 collection 视图重新加载我得到 2 个相同的新 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()
        }

    })
}

就像我说的,在 viewDidLoad 上,一切都完美无缺,数据库也完美地保存了一切,没有双重 posts 也没有双重位置..只有当我 post 一个新的和回到我的 collection 视图,fetchPosts 再次运行,一切都很好,直到最后 2 个它添加另一个 Post 到 posts 那是我新的两倍post.

仅供参考,我的新 Posting 功能从未触及 posts,这一切都在我的 collectionView 控制器上完成。

我一直在试图弄清楚这个额外的 post 是从哪里来的,但是没有骰子

已回答 我解决了这个问题,如果有人想做类似的事情,我 post 在下面说明了我是如何修复它的作为答案

当您调用 circleQuery.observe(.keyEntered 时,它会启动一个观察者。这将继续观察进入查询范围的键,直到您删除观察者。由于您永远不会删除观察者,因此第二次调用 fetchPosts 实际上是在添加第二个观察者,这意味着您的代码将针对范围内的每个键调用两次。

在您的 class 中定义句柄和查询,这样您就可以在 fetchPosts 函数之外访问它

var handle: DatabaseHandle!
var circleQuery: GFCircleQuery!

要删除观察者,请确保保留附加观察者时返回的句柄:

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

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

然后通过调用 fetchPosts completion Handler 移除观察者:

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

如果您在调用 fetchPosts 时只是在查询范围内寻找对象并且不想继续观察,您通常会在 GeoFire 为所有对象调用后移除观察者初始对象,即 'ready' with the query:

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