【问题标题】:how to detach a listener in a local scope?如何在本地范围内分离侦听器?
【发布时间】:2021-05-07 22:25:43
【问题描述】:

当按下按钮时,我想在 viewController 中分离 snapshotListener。我正在阅读其他堆栈溢出问题和文档,他们正在同一个函数中为侦听器调用 remove 方法。我尝试在我的情况下这样做,但我的 snapshotListener 根本没有工作。

这是我想要调整的函数和代码块。

@objc func doneTapped() {
    
    let updateListener = db.collection("school_users/\(user?.uid)/events").whereField("event_name", isEqualTo: navigationItem.title).addSnapshotListener(includeMetadataChanges: true) { (querySnapshot, error) in
        if let error = error {
            print("There was an error fetching the documents: \(error)")
        } else {
            self.eventName = querySnapshot!.documents.map { document in
                return EventName(eventName: (document.get("event_name") as! String))
            }
            
            self.db.document("school_users/\(self.user?.uid)/events/\(self.docIDUneditableTextF.text!)").updateData(["event_date": self.dateEditableTextF.text, "event_cost": self.costEditableTextF.text, "for_grades": self.gradesEditableTextF.text]) { (error) in
                if let error = error {
                    print("There was an error updating the document: \(error)")
                } else {
                   print("The document was successfully updated."
                }
            }
        }
    }
    
    dateEditableTextF.resignFirstResponder()
    dateEditableTextF.isEnabled = false
    
    costEditableTextF.resignFirstResponder()
    costEditableTextF.isEnabled = false
    
    
    gradesEditableTextF.resignFirstResponder()
    gradesEditableTextF.isEnabled = false
    
    navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(editTapped))

}

我尝试调用updateListener.remove(),但它使我的快照监听器根本无法工作,而且当文档更新时,打印语句永远不会结束,这也是因为监听器仍然处于活动状态还是另一个问题?

【问题讨论】:

    标签: swift google-cloud-platform google-cloud-firestore listener observers


    【解决方案1】:

    addSnapshotListener 将在数据更改时为您提供更新。我不清楚为什么要立即删除侦听器,如果您确实想要接收更新 - 而且,正如您所指出的,立即删除它基本上会导致它根本不起作用。也许发布一个链接,指向您看到您引用的代码的一些帖子/文档,有人可以深入了解正在发生的事情。

    我怀疑您实际上并不需要更新数据。在这种情况下,您可以改用.getDocuments()。请参阅此处的 Firestore 文档,了解获取数据的不同方式:https://firebase.google.com/docs/firestore/query-data/get-data

    第二个问题(无限打印)与第一个问题有关。因为您有一个侦听器,它将在数据更改时返回更新,当您执行第二次数据库调用(您的updateData)时,它会更新您的数据,再次触发侦听器。这将继续循环,因为他们将继续互相调用。这是另一个迹象,表明您可能实际上并不想要一个侦听器,而是一个获取数据的调用。如果您确实确实想要更新,则必须找到一种方法来解耦第二个请求,以免陷入循环。

    基于 cmets 更新:(在不同函数中移除监听器的示例)

    在您的视图、视图控制器等上,为侦听器声明一个属性:

    class MyViewController : UIViewController {
      private var documentListener: ListenerRegistration? //assuming that ListenerRegistration is the correct type here, but you can check the current type of your updateListener to check
    }
    

    然后,在您的函数中,将您的侦听器设置为:

    documentListener = db.collection("school_users/\(user?.uid)/events").whereField("event_name", isEqualTo: navigationItem.title).addSnapshotListener()...
    

    然后,稍后(如viewDidDisappear),您可以将其删除:

    documentListener?.remove()
    

    【讨论】:

    • 我不想立即删除监听器我只是想找出一种方法来阻止它,因为监听器不会停止并最终在 30 分钟内超过每日限制。另外,你必须解释解耦,我不知道你的第二个请求解耦是什么意思。我肯定想要更新,因为实时快照监听器确实在应用程序中发挥了重要作用。如果您可以解释解耦或将我重定向到一个非常感谢的来源。我看到的文档的链接。 firebase.google.com/docs/firestore/query-data/…@jnpdx
    • 您刚刚发送的那个链接并不一定表明 remove() 在同一个函数中被调用 - 它只是向您展示如何删除它
    • 是的,我知道并且我想知道如何在不同的函数中删除该监听器调用,例如 viewDidDisappear() 或类似 @jnpdx
    • 通过解耦,我的意思是你不能在回调中调用 updateData() 到你的快照监听器,因为它最终会调用一个无限循环,就像你已经经历过的那样,我已经描述过。我不知道将您链接到的来源,尽管您可以谷歌“递归循环”以了解更多信息。如何处理这个问题的决定是一个架构问题。
    • 我将更新我的答案以反映在不同的函数中删除侦听器......一秒钟。
    猜你喜欢
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 2018-08-17
    相关资源
    最近更新 更多