为啥添加单个文档时,Firestore 侦听器会返回 .add 两次?
Posted
技术标签:
【中文标题】为啥添加单个文档时,Firestore 侦听器会返回 .add 两次?【英文标题】:Why is a firestore listener returning .added twice when a single document is added?为什么添加单个文档时,Firestore 侦听器会返回 .add 两次? 【发布时间】:2017-12-12 01:22:27 【问题描述】:我正在使用谷歌地图,我的用户可以在地图上添加地图标记。 地图标记存储在 Firestore 中。 我有一个监听数据库的监听器。 每个用户只能提交一个地图标记 - 因此数据库中每个用户只有一个文档。但他们可以修改标记的 lat 和 lng。
我的 Firestore 设置为:
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
添加一个标记。当他们提交标记时,我使用 unwind segue 让他们回到MapController
。 (我不会在任何阶段将监听器与MapController
分离)。
// 添加标记控制器
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)
会执行两次,并且 print(" added") 会发生两次,即使 currentuser fireauth id 只是在集合下添加了一次submittedMarkers
。
当我打印出 diff.document.ID
时,我得到了已经在 firestore 中的用户和刚刚添加新文档的当前用户的 fireauth id。
我怀疑我不太明白监听器是如何工作的。我以为if(diff = .added)
会监听submittedMarkers
集合,并且只会在添加新文档时触发一次。
我不确定问题是否是:
-
我离开
MapController
时没有分离监听器 -> AddMarkerController
?
听众在viewWillAppear
而不是viewDidLoad
,但从阅读firebase博客来看,它应该在viewWillAppear
无论是 snapshot.documentChanges.forEach
在每次发生变化时循环整个快照
【问题讨论】:
【参考方案1】:第一个added
是在您调用setData()
时立即触发的本地事件。第二个added
是服务器写入数据后的确认事件。
请参阅文档中的events for local changes 部分。
另一个原因可能是您未能取消注册观察者。如果您在 viewWillAppear
中注册了您的观察者,请在 viewWillDisappear
或 viewDidDisappear
中取消注册。如果你不这样做,你最终会为同一个事件有多个观察者,因此会有多个调用。
【讨论】:
嗨@Frank。我仍然有同样的行为。我以第二个用户身份登录我的应用程序。 firestore 中的单个标记已正确加载,并且 diff = . added 被触发一次。但是,每次我从 MapController 转到另一个控制器并返回时,viewWillAppear 都会像往常一样执行,但我发现自己又回到了 diff == .add 中,每次都再次加载服务器数据。我在原始帖子的末尾进行了更新,并提供了更多信息。我想知道我的听众是否在每次我回到 viewWillAppear 时都重新注册。谢谢。 啊,可能是这样。我必须承认我没有阅读 all 您问题中的代码+描述(通常:少即是多)。如果您在viewWillAppear
中注册您的观察者,请在ViewWillDisappear
或viewDidDisappear
中取消注册。如果你不这样做,你最终会为同一个事件有多个观察者,因此会有多个调用。以上是关于为啥添加单个文档时,Firestore 侦听器会返回 .add 两次?的主要内容,如果未能解决你的问题,请参考以下文章
添加新文档时,kotlin firestore 未更新我的 android 应用程序
TypeError:无法读取 null 的属性“Symbol(dartx._get)”(在 Flutter 中添加 Firestore 侦听器时)
为啥 Firebase 数据库(Firestore)不添加文档