为什么在添加单个文档时,firestore侦听器返回两次. [英] Why is a firestore listener returning .added twice when a single document is added?

查看:30
本文介绍了为什么在添加单个文档时,firestore侦听器返回两次.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Google地图,我的用户可以在地图上添加地图标记.地图标记存储在Firestore中.我有一个监听数据库的监听器.每个用户只能提交一个地图标记-因此数据库中每个用户只有一个文档.但是他们可以修改标记的经度和纬度.

我的消防站设置为:

  root-SubmittedMarkers(集合)-fireauthID_1(文档)-栏位1(lat):-栏位2(lng):-fireauthID_2(文档)-栏位1(lat):-栏位2(lng): 

//MapController.swift

 覆盖功能funC viewWillAppear(_动画:Bool){listener = db.collection("submittedMarkers").addSnapshotListener {querySnapshot,错误警卫队让快照= querySnapshot其他{print(读取快照时出错:\(错误!)")返回}snapshot.documentChanges.forEach {差异输入如果(diff.type == .add){打印(添加")}if(diff.type == .modified){打印(在Firestore中修改了文档")}}}} 

目前,调试时,我在Firestore中只有一个用户,在 submittedMarkers -> {fireauthId} 下只有一个文档.

当我的应用加载时,将当前存在的单个标记与单个打印语句添加"一起添加到地图.这样行得通.

这是我遇到的问题.

当新用户注册并获取fireauth ID时,他们便可以从 AddMarkerController 添加标记.当他们提交标记时,我会使用轻松的搜索将其返回到 MapController .(在任何阶段,我都不会从 MapController 分离侦听器.)

//AddMarkerController

  docref = db.collection("submittedMarkers").document(currentUserId)docref?.setData([纬度":纬度,经度":经度,"date_time":日期!,距离":dist,速度":速度],选项:SetOptions.merge()){err in如果让err = err {print(书写文档时出错:\(err)")} 别的 {}} 

但是我发现,当他们回到 MapController 时,如果 type == .added> 执行了两次,并且print(即使已在集合 submittedMarkers 下一次添加了currentuser fireauth ID,也会发生两次.

当我打印出 diff.document.ID 时,我同时获得了已经在firestore中的用户和刚刚添加新文档的当前用户的fireauth ID.

我怀疑我不太了解收听者的工作方式.我以为 if(diff = .added)会监听 submittedMarkers 集合,并且仅在添加新文档时触发一次.

我不确定问题是否存在:

  1. 离开 MapController -> AddMarkerController 时,我不会分离侦听器吗?
  2. 侦听器位于 viewWillAppear 中,而不位于 viewDidLoad 中,但通过阅读Firebase博客,侦听器应位于 viewWillAppear
  3. 是否是 snapshot.documentChanges.forEach 每当每次更改时都会遍历整个快照

解决方案

添加的第一个 是在调用 setData()时立即触发的本地事件.第二个添加的 是服务器写入数据后的确认事件.

请参见有关本地更改的事件文档中的部分.

另一个原因可能是您未能注销观察者的注册.如果您在 viewWillAppear 中注册了观察者,请在 viewWillDisappear viewDidDisappear 中取消注册.如果不这样做,最终将为同一个事件带来多个观察者,从而有多个调用.

I'm using google maps and my users can add a map marker to the map. The map markers are stored in firestore. I have a listener that listens in to the database. Each user can only submit one map marker - so there is only one document for each user in the database. But they can modify the lat and lng of their marker.

My firestore is set out as:

root
  - submittedMarkers (collection)
          - fireauthID_1 (document)
                - field 1 (lat): 
                - field 2 (lng):
          - fireauthID_2 (document)
                - field 1 (lat):
                - field 2 (lng): 

// MapController.swift

override func viewWillAppear(_ animated: Bool){
    listener = db.collection("submittedMarkers").addSnapshotListener { querySnapshot, error in
        guard let snapshot = querySnapshot else {
            print("Error fetching snapshots: \(error!)")
            return
        }
        snapshot.documentChanges.forEach { diff in   
            if (diff.type == .added){
                print("added")
            }
            if(diff.type == .modified) {
                print("modified the document in firestore")
            }
        }
    }
}

At the moment for debugging I only have one user in firestore and one document under submittedMarkers -> {fireauthId}.

When my app loads the single marker that currently exists is added to the map along with a single print statement "added". So that works.

Here is the problem I've encountered.

When a new user registers and gets a fireauth id they can then go and add a marker from the AddMarkerController. When they submit the marker i use an unwind segue to get them back to the MapController. (I don't detach the listener at any stage from the MapController).

// AddMarkerController

docref = db.collection("submittedMarkers").document(currentUserId)
docref?.setData([
    "latitude": latitude,
    "longitude": longitude,
    "date_time": date!,
    "distance": dist, 
    "speed": speed
], options: SetOptions.merge()) { err in
    if let err = err {
        print("Error writing document: \(err)")
    } else {

    }
}

But what I have found is that when they have come back to the MapController the if (diff.type == .added) is executed twice and print("added") happens twice even though the currentuser fireauth id is added just the once under the collection submittedMarkers.

And when I print out the diff.document.ID i'm getting both the fireauth id of the user who was already in firestore and the current user who just added a new document.

I suspect I don't quite get then how the listener works. I thought if(diff = .added) would listen to the submittedMarkers collection and only fire once when a new document is added.

I wasn't sure if the issue is:

  1. I don't detach the listener when I leave the MapController -> AddMarkerController?
  2. The listener is in viewWillAppear and not viewDidLoad but from reading the firebase blog it should be in viewWillAppear
  3. Whether it's the snapshot.documentChanges.forEach which is looping through the entire snapshot each time something changes

解决方案

The first added is the local event that is fired as soon as you call setData(). The second added is the acknowledged event after the server has written the data.

See the events for local changes section in the documentation.

Another reason might be that you fail to unregister your observer. If you register your observer in viewWillAppear, unregister it in viewWillDisappear or viewDidDisappear . If you don't, you'll end up with multiple observers for the same event and thus with multiple invocations.

这篇关于为什么在添加单个文档时,firestore侦听器返回两次.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆