为什么在添加单个文档时,firestore侦听器返回.added两次?

时间:2017-12-12 01:22:27

标签: swift google-cloud-firestore

我使用谷歌地图,我的用户可以在地图上添加地图标记。 地图标记存储在firestore中。 我有一个监听数据库的监听器。 每个用户只能提交一个地图标记 - 因此数据库中每个用户只有一个文档。但是他们可以修改标记的lat和lng。

我的火店名列如下:

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")
            }
        }
    }
}

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

当我的应用加载时,当前存在的单个标记会与单个打印语句一起添加到地图中并添加"。这样才有用。

这是我遇到的问题。

当新用户注册并获得fireauth id时,他们可以从AddMarkerController添加标记。当他们提交标记时,我使用展开segue将其返回MapController。 (我不会在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 {

    }
}

但我发现,当他们回到MapController时,if (diff.type == .added)被执行两次并且打印("添加")发生两次,即使当前用户fireauth id仅在集合submittedMarkers下添加一次。

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

我怀疑我不太了解听众是如何工作的。我认为if(diff = .added)会收听submittedMarkers集合,只会在添加新文档时触发一次。

我不确定问题是:

  1. 当我离开MapController - >时,我不会分离听众。 AddMarkerController
  2. 听众位于viewWillAppear而不是viewDidLoad,但是在阅读firebase博客时,它应位于viewWillAppear
  3. 每次更改内容时,是否snapshot.documentChanges.forEach循环遍历整个快照

1 个答案:

答案 0 :(得分:3)

第一个added是您拨打setData()后立即触发的本地事件。第二个added是服务器写入数据后的确认事件。

请参阅文档中的events for local changes部分。

另一个原因可能是您无法取消注册您的观察者。如果您在viewWillAppear注册观察者,请在viewWillDisappearviewDidDisappear中取消注册。如果你不这样做,你最终将会有多个观察者参加同一个活动,因此会有多次调用。