@Published property in @EnvironmentObject doesn't update the root view of my application

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.

How it should work

1. A user clicks Sign in with Apple button
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.

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



Accepted Reply

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.

Replies

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.