Updating @Published variable of an ObservableObject inside child view
One possibility would be to insert the UserAuth
object from the ContentView
into the subviews as an EnvironmentObject
.
struct ContentView: View { @ObservedObject var userAuth = UserAuth() var body: some View { Group { if userAuth.isLoggedIn { MainView() } else { AccountView() .environmentObject(userAuth) } } }}
Now userAuth
is accessible in AccountView
and all its subviews (e.g. LoginView
):
struct LoginView: View { // Access to the environment object @EnvironmentObject private var userAuth: UserAuth var body: some View { VStack { Button(action: { return self.login() }) { Text("Log in") .padding() .foregroundColor(Color.white) .background(Color.green) .cornerRadius(10) } } } func login() { // Update the value on the main thread DispatchQueue.main.async { self.userAuth.isLoggedIn = true } }}
It may be necessary to insert the EnvironmentObject into the LoginView
manually. You can do this by accessing it in the AccountView
and inserting it in the LoginView
:
struct AccountView: View { @State private var toggleSheet = false // Access the value, that was inserted in `ContentView` @EnvironmentObject private var userAuth: UserAuth var body: some View { VStack { Spacer() Button(action: { self.toggleSheet.toggle() }){ Text("Toggle Modal") .padding() .foregroundColor(Color.white) .background(Color.blue) .cornerRadius(10) } .sheet(isPresented: self.$toggleSheet){ LoginView() // Insert UserAuth object again .environmentObject(self.userAuth) } Spacer() } }}
Further Reading
WWDC 2019 Video | Hacking with Swift Example