8.3 C
London
Wednesday, September 11, 2024

ios – swiftui navigationStack initialising path with onAppear not displaying right display screen


I am new to swiftui growth. Attempting to construct my first actual app! I am nonetheless tackling navigation and authentication the place I am attempting to show the right screens whether or not the authState is unauthenticated or authenticated. nevertheless, my app is not launching on the right display screen relying on the state it simply crashes with no error message given.

I’ve a Router class with a single Routes enum for all my routes.

remaining class Router: ObservableObject {
  public enum Routes: Hashable {
    case touchdown
    case emailAuth
    case dwelling
  }

  @Revealed var path: [Routes] = []
  
  func navigate(to vacation spot: Routes) {
    path.append(vacation spot)
  }
  
  func navigateBack() {
    path.removeLast()
  }
  
  func navigateToRoot() {
    path.removeLast(path.depend)
  }
}

that is my AuthViewModel the place I am utilizing firebase addStateDidChangeListener to pay attention for state modifications:

enum AuthState {
  case unAuthenticated
  case authenticated
}

@MainActor
class AuthViewModel: ObservableObject {    
  @AppStorage("electronic mail") var emailStore: String?
  @Revealed var electronic mail = ""
  @Revealed var errorMessage = ""
  
  @Revealed var authState: AuthState = .unAuthenticated
  @Revealed var consumer: Person?
  @Revealed var userEmail = ""
  
  init() {
    registerAuthStateHandler()
  }
  
  non-public var authStateHandle: AuthStateDidChangeListenerHandle?
  
  func registerAuthStateHandler() {
    if authStateHandle == nil {
      authStateHandle = Auth.auth().addStateDidChangeListener{auth, consumer in
        self.consumer = consumer
        self.userEmail = consumer?.electronic mail ?? "(unknown)"
        
        if (consumer != nil) {
          self.authState = .authenticated
        } else {
          self.authState = .unAuthenticated
        }
        print("Curr authState: (self.authState)")
      }
    }
  }
}

...

I feel I am appropriately declaring my router with @StateObject inside my view?:

struct ContentView: View {
  @StateObject var authViewModel: AuthViewModel = AuthViewModel()
  @StateObject var router: Router = Router()
  
  var physique: some View {
    NavigationStack(path: $router.path) {
//    Textual content("Loading...")
      LandingScreen(path: $router.path)
        .navigationDestination(for: Router.Routes.self) { route in
          swap route {
          case .touchdown:
            let _ = print("touchdown")
            LandingScreen(path: $router.path)
          case .emailAuth:
            AuthEmail(path: $router.path)
          case .dwelling:
            Textual content("TODO: dwelling web page")
          }
        }
    }
    .onAppear {
      print("Curr authState: (authViewModel.authState)")
      if (authViewModel.authState == .authenticated) {
        router.path = [.home]
      } else {
        router.path = [.landing]
      }
      print(router.path)
    }
    .environmentObject(router)
    .environmentObject(authViewModel)
  }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
      .environmentObject(AuthViewModel())
      .environmentObject(Router())
  }
}

inside my subviews, I’ve one thing like:

struct LandingScreen: View {
  @EnvironmentObject var authViewModel: AuthViewModel
  @Binding var path: [Router.Routes]
  
    var physique: some View {
       // ... 
        NavigationStack {
            NavigationLink(worth: Router.Routes.emailAuth) {
              Textual content("Proceed with electronic mail")
            }
        }
    }

what I’ve tried was altering the preliminary display screen in my NavigationStack to only a easy Textual content("Loading...") nevertheless, my display screen stays on the “loading…” display screen and doesn’t change the display screen to the LandingScreen. regardless of my print logs saying that it has set the trail appropriately:

Curr authState: unAuthenticated
[app.Router.Routes.landing]
touchdown

I’ve additionally tried transferring my onAppear code to an init() as an alternative but it surely’s anticipated that init known as a number of occasions and nonetheless stays on the loading display screen in order that’s a no go…
I’ve additionally tried transferring the init() as much as the Router however I am getting the identical subject.

Latest news
Related news

LEAVE A REPLY

Please enter your comment!
Please enter your name here