Hello.
I am trying to make a router object for my application using @EnvironmentObject. But the problem is the @Published property doesn't update the root view when the root view type is updated.
2. Update the router.currentPage property of @EnvironmentObject when a user logs in successfully.
3. RootView get notified for updating router.currentPage and change the root view in accordance to the updated currentPage type.
Here are my codes below.
I am trying to make a router object for my application using @EnvironmentObject. But the problem is the @Published property doesn't update the root view when the root view type is updated.
How it should work
1. A user clicks Sign in with Apple button2. Update the router.currentPage property of @EnvironmentObject when a user logs in successfully.
3. RootView get notified for updating router.currentPage and change the root view in accordance to the updated currentPage type.
Here are my codes below.
MainApp.swift
Code Block var body: some Scene { WindowGroup { RootView().environmentObject(ViewRouter()) } }
ViewRouter.swift
Code Block enum Page { case signin case tasklist } final class ViewRouter: ObservableObject { @Published var currentPage: Page = .signin }
RootView.swift
Code Block struct RootView: View { @EnvironmentObject var router: ViewRouter var body: some View { if router.currentPage == .signin { SigninView() } else { TaskListView() } } }
SigninView.swift
Code Block struct SigninView: View { @EnvironmentObject var router: ViewRouter @State var signInHandler: SignInWithAppleCoordinator? var window: UIWindow? { guard let scene = UIApplication.shared.connectedScenes.first, let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate, let window = windowSceneDelegate.window else { return nil } return window } var body: some View { MyAppleIDButton().colorScheme(.light) .frame(width: 280, height: 38, alignment: .center) .onTapGesture { signInWithAppleButtonTapped() } } func signInWithAppleButtonTapped() { guard let _window = self.window else { return } signInHandler = SignInWithAppleCoordinator(window: _window) signInHandler?.signIn { (user) in router.currentPage = .tasklist } } }
Update
I think I found an answer to this issue.
I created a state isLoggedIn which is checking whether or not Sign in with Apple is done successfully.
Code Block @State var isLoggedIn: Bool = false
Then I added View Modifier onChange which is checking the value change of isLoggedIn above. Inside the onChange I assigned a new value to router.currentPage like below.
Code Block .onChange(of: isLoggedIn, perform: { isLoggedIn in if isLoggedIn { router.currentPage = .tasklist } else { router.currentPage = .signin } })
But I am still not sure of why it doesn't work in the closure of SigninWithApple button.