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
不是为了管理登录状态,为什么不在其上创建一个名为login
或logout
的函数来执行与登录/注销相关的所有操作(例如添加侦听器)。然后,不要在视图中管理您的登录状态 (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 未编译
CKReference 的 CloudKit 订阅通知未按预期工作
MobileFirst - Android 推送 - 无法订阅,通知令牌未在服务器上更新
SwiftUI-> 线程 1:致命错误:未找到 MyObject.Type 类型的可观察对象(工作表中的 EnvironmentObject)