【问题标题】:What are the benefits of storing a Firebase listener in a property SwiftUI?在属性 SwiftUI 中存储 Firebase 侦听器有什么好处?
【发布时间】:2021-07-18 06:00:00
【问题描述】:

我想知道在属性中存储 Firebase 侦听器(例如 AuthStateDidChangeListener 或文档快照侦听器)有什么好处。

例如:

final class SessionStore: ObservableObject {
    @Published private(set) var currentUser: User?
    
    private var handle: AuthStateDidChangeListenerHandle?
    private var listener: ListenerRegistration?

    func listen() {
        guard handle == nil else { return }
        // This code will work irrespective of whether I put "handle =" or not
        handle = Auth.auth().addStateDidChangeListener { auth, _ in
            if let user = auth.currentUser {
                self.currentUser = user
            } else {
                self.currentUser = nil
            }
        }
    }
}

如果我没有将 Auth State Change Listener 存储在 handle 属性中,后果会是什么?据我所知,代码的工作原理相同。同样,对于文档快照侦听器,我是否将侦听器存储在属性中有什么区别:

listener = db.collection("col1").document("doc1").addSnapshotListener { snapshot, error in 
  \\...
}

对比不存储它,只是拥有:

db.collection("col1").document("doc1").addSnapshotListener { snapshot, error in 
  \\...
}

总结:AuthStateDidChangeListener 或文档快照侦听器存储在handlelistener 等属性中与根本不存储有什么区别?不保存会有什么后果?

【问题讨论】:

    标签: ios firebase google-cloud-firestore swiftui firebase-authentication


    【解决方案1】:

    通过使用方法addSomeListner() -> Listner,您正在创建一个特殊的对象Listner,它允许您在事件发生时执行操作。

    创建后,Listner 将开始侦听传入事件,而不管您侦听的“数据”的状态或使用它的上下文。

    这是什么意思?有什么影响?

    示例

    您的文档一旦被删除,就无法使用相同的 ID 重新创建。

    想象一个页面,其中显示名为“DOCUMENT_UNIQUE_A”的文档的数据。所以你会像这样创建一个监听器:

    let myListner = document("DOCUMENT_UNIQUE_A").addSnapShotListner(\**/)
    

    在某个时候,某人或用户会删除该文档。发生这种情况时,您的侦听器将收到“document-deleted”事件,您将执行一些操作(例如通过从列表中删除文档或其他方式来更新您的 UI)。

    现在是重要的部分。一开始,我说过Listener 是一个不断等待事件的对象。但在我们的例子中,这个监听器永远不会收到新的事件,因为我们永远不会有一个具有相同 id 的文档。

    通过存储监听器,您有机会将其移除并释放其内存空间。

    myListner.remove()
    

    所以来回答你的问题。

    1. 为什么这两个代码都有效?因为 Firebase 创建了一个对您的侦听器的强引用,以避免对象被自动释放。
    2. 有什么区别?通过存储监听器,您可以控制它,并且可以在您认为合适的时间删除它。

    何时应删除侦听器的示例

    1. 关闭视图后,其内容取决于该侦听器。
    2. 如果您在 List 中并且每一行都有一个 Listener,则应考虑在 Row 未显示时停止它们。
    3. 如果您有一个依赖于另一个侦听器的侦听器。

    AuthListner 呢?

    身份验证状态侦听器是一种特殊情况,因为在您的应用会话生命周期中,您总是可以期待用户事件(登录-注销-无效),因此永远不要删除或存储它通常是一个好习惯。

    但请注意,由于末尾是普通的Listener,因此对其应用完全相同的规则。

    【讨论】:

    • 您好,感谢您的精彩回复。关于 firebase 如何创建对对象的强引用,我仍然有一些疑问。假设我连续多次调用Auth.auth().addStateDidChangeListener { doc, err in //... }(不存储它),这会创建多个侦听器吗?退出应用程序(从多任务用户界面向上滑动)是否会取消分配所有创建的侦听器而不将它们存储在属性中?还是堆积起来?
    • 我自己做了一些实验,这就是我的发现:退出应用程序会释放所有侦听器(因为如果我重新启动应用程序,数据库更新不会触发 UI 更改)。多次调用addSnapshotListener 实际上会创建多个侦听器(但是当您退出应用程序时,所有侦听器都会被停用)。我错过了任何细微之处吗?
    • 谢谢,@rayaantaneja。当您说“退出应用程序”时,您的意思是在应用程序管理器中强制关闭/杀死应用程序?或者你的意思是当应用程序进入后台时?无论如何,我建议在您的听众中放置一些打印件,以查看发生了什么。你绝对应该看看 Swift 如何管理引用:docs.swift.org/swift-book/LanguageGuide/… 以及如何在闭包范围内管理引用。这肯定会帮助你理解下划线的“问题”。
    猜你喜欢
    • 1970-01-01
    • 2016-01-17
    • 2018-09-09
    相关资源
    最近更新 更多