Historically using UIKit
we have always used the Coordinator Pattern to handle Navigation.
Starting a new app in SwiftUI
however it is not clear how to handle this.
For example, our currently flow would be:
- App Launches
- App Coordinator Starts
- Loads "Start Scene"
- Start scene checks auth state and calls delegate on App Coordinator
- App Coordinator starts
showHomeScene
orshowAuthScene
Something like
final class AppCoordinator: BaseCoordinator {
private(set) var navigationController: UINavigationController?
init(navigationController: UINavigationController?) {
self.navigationController = navigationController
}
override func start() {
showStartScene()
}
private func showStartScene() {
let configurator = StartConfigurator()
let viewController = configurator.create(self)
navigationController?.setViewControllers([viewController], animated: false)
}
private func showHomeScene() {
let coordinator = HomeCoordinator(self, navigationController: navigationController)
store(coordinator: coordinator)
coordinator.start()
}
private func showAuthScene() {
let coordinator = AuthCoordinator(self, navigationController: navigationController)
store(coordinator: coordinator)
coordinator.start()
}
}
extension AppCoordinator: StartSceneDelegate {
func userNeedsToAuthenticate() {
showAuthScene()
}
func userIsAuthenticated() {
showHomeScene()
}
}
However as we are not using UIViewController
how does navigationController?.setViewControllers([viewController], animated: false)
work?
Should we still just set using a UIHostingController
?
Something like -
navigationController?.setViewControllers([UIHostingController(rootView: StartView())], animated: false)
It seems a bit weird as I don't believe the SwiftUI views will really make use a UINavigationController
as they use NavigationView
and NavigationLink
.
Unless the UINavigationController
really just serves as a wrapper?
I was considering using@EnvironmentObject
within the coordinator and based on the auth state replacing the root view controller in the coordinator also.
enum States { case A: case B }
and some view model holding that state, and root view which depending of the state in view model shows either ViewA or ViewB, and coordinator can manage switching those states in shared view model, which in case of SwiftUI can be EnvironmentObject set to root. – Maltese