EnvironmentObject 未通知订阅的视图的更改

Posted

技术标签:

【中文标题】EnvironmentObject 未通知订阅的视图的更改【英文标题】:EnvironmentObject is not notifying changes to views that are subscribed 【发布时间】:2021-03-17 14:52:13 【问题描述】:

我有这个应用程序,我正在使用 firebase firestore 实现注销功能。我想要做的是在用户注销时分离我所有的快照监听器。我使用 environmentObject 来观察用户何时注销。

class StatusManager: ObservableObject

@Published var didLogOut: Bool = false


我将对象注入到环境中。然后,我在每个具有侦听器的视图中捕获对象。

    @EnvironmentObject var statusManager: StatusManager

这就是我计划在用户注销后分离监听器的方式。

        .onAppear(perform: 

        
        if statusManager.didLogOut == false
            

        notifyListener = db.collectionGroup("resources").whereField("control", isEqualTo: true).addSnapshotListener  (snapshot, err) in
            
          //All the functionality
    

        else
            notifyListener?.remove()
        
)

这是用户注销的地方。

                Button(action: 
                
                isLoggedIn = false
                lastLoggedEmail = ""
                lastLoggedUserType = ""
                lastLoggedUserPassword = ""
                statusManager.didLogOut = true

                try? Auth.auth().signOut()
                
                navStack.pop(to: .root)
                
            , label: 
                Text("Sign Out")
                    .font(Font.custom("Roboto-Light", size: 14))
                
            )

问题是,一旦改变了 didLogOut 状态,我使用快照侦听器的代码就永远不会重新读取。因此,快照监听器永远不会被移除。

【问题讨论】:

看起来像是架构问题。如果StatusManager 不是为了管理登录状态,为什么不在其上创建一个名为loginlogout 的函数来执行与登录/注销相关的所有操作(例如添加侦听器)。然后,不要在视图中管理您的登录状态 (isLoggedIn),而是在您的 StatusManager 上设置一个 @Published 参数。您可能完全摆脱了didLogOut 【参考方案1】:

如果您的 notifyListener 逻辑所在的视图未重新绘制(如从树中删除并再次重新添加),则该代码只会运行一次(当它第一次显示时,因为它是一个 onAppear 块)。如果是这种情况,您可以改用 onChange 块。

.onChange(of: statusManager.didLogOut)  value
       if value == false 
           notifyListener = db.collectionGroup("resources").whereField("control", isEqualTo: true).addSnapshotListener  (snapshot, err) in 
        else 
           notifyListener?.remove()
       
)

【讨论】:

以上是关于EnvironmentObject 未通知订阅的视图的更改的主要内容,如果未能解决你的问题,请参考以下文章

@EnvironmentObject 符合协议:Xcode 未编译

向未订阅某个主题的多个设备发送通知

未收到来自 CloudKit 订阅的推送通知

CKReference 的 CloudKit 订阅通知未按预期工作

MobileFirst - Android 推送 - 无法订阅,通知令牌未在服务器上更新

SwiftUI-> 线程 1:致命错误:未找到 MyObject.Type 类型的可观察对象(工作表中的 EnvironmentObject)