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.