'SwiftUI private route based on Authentication Status

I need to implement a mechanism just like react private and public route on swiftUI. Basically I have tens of views and some of these views requires authentication based on user logged in status. So far I have tried to hold current screen in an Environment Object as show in following class

    enum Routes {
    case screenA,
         screenB,
         screenC,
         screenD,
         screenE,
         screenF,
         screenG,
         loginScreen
    
    var isAuthRequired: Bool {
            if case . screenA = self {
                return true
            } else if case . screenD = self {
                return true
            } else {
                return false
            }
        }
}

class AuthenticatedRoute: ObservableObject {
    
    @Published var currentRoute: Routes
    
    init(){
        self.currentRoute = . screenA
    }
}

And on my main screen I check every time the current screen change whether user loggedin and current page require authentication.

struct MainView: View {
    @StateObject var authenticatedRoute = AuthenticatedRoute()
    @EnvironmentObject var userAuth: UserAuth
    
    var body: some View {
        mainView()
            .environmentObject(authenticatedRoute)
    }
    
    
    @ViewBuilder
    func mainView() -> some View {
        if (self.authenticatedRoute.currentRoute.isAuthRequired && !userAuth.isLoggedIn) {
            LoginView()
        }
        else {
            DefaultTabView()
        }
    }
}

And this is an example of how I keep changing this environment variable. I change the environment object onAppear event method of view.

struct ScreenA: View {
    @EnvironmentObject var authenticatedRoute: AuthenticatedRoute
    
    var body: some View {
        NavigationView {
            someContent()
        }.onAppear {
            authenticatedRoute.currentRoute = .screenA
        }
    }
}

While this approach works for most cases for some reason it behave strange when a screen is in tab navigation. Also I do not feel comfortable with this solution, that I need to change screen name manually on every single page, and checking authentication status in main view. I think it would be better somehow if I can write a kind of interceptor before every page change and check if desired destination requires authentication and if user is authenticated but I could not find a way manage this. I'm relatively new to iOS development and had experience with react native but this should not be so hard to implement in my opinion since this is a requirement for most applications.

So basically I need to implement a private and public router in swiftUI or intercept every page change so I should not modify environment variable on each pages manually and should not check conditions in MainView inside a function.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source