首页 > 解决方案 > EnvironmentObject is not notifying changes to views that are subscribed

问题描述

I have this app where I am implementing a logout feature with firebase firestore. What I want to do is detach all my snapshotListeners when the user logs out. I use an environmentObject to observe when the user logged out.

class StatusManager: ObservableObject{

@Published var didLogOut: Bool = false

}

I inject the object into the environment. Then, I catch the object in every view that has a listener.

    @EnvironmentObject var statusManager: StatusManager

This is how I plan to detach the listener once the user logs out.

        .onAppear(perform: {

        
        if statusManager.didLogOut == false{
            

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

And this is where the user logs out.

                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))
                
            })

The problem is, The code where I use the snapshot listener is never reread once the didLogOut state is changed. Therefore, the snapshot listener is never removed.

标签: iosswiftfirebaseswiftui

解决方案


If the view where your notifyListener logic is not re-drawn (as in removed from the tree and re-added again) that code will only run once (when it's shown for the first time, since it's an onAppear block). If that's the case you can use the onChange block instead.

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

推荐阅读