Going off of this article about using coordinator pattern in SwiftUI, it feels unnatural to rely on UIKit’s UINavigationController to do the push/pop/present.
Relevant code:
import SwiftUI
open class Coordinator<Router: NavigationRouter>: ObservableObject {
public let navigationController: UINavigationController
public let startingRoute: Router?
public init(navigationController: UINavigationController = .init(), startingRoute: Router? = nil) {
self.navigationController = navigationController
self.startingRoute = startingRoute
}
public func start() {
guard let route = startingRoute else { return }
show(route)
}
public func show(_ route: Router, animated: Bool = true) {
let view = route.view()
let viewWithCoordinator = view.environmentObject(self)
let viewController = UIHostingController(rootView: viewWithCoordinator)
switch route.transition {
case .push:
navigationController.pushViewController(viewController, animated: animated)
case .presentModally:
viewController.modalPresentationStyle = .formSheet
navigationController.present(viewController, animated: animated)
case .presentFullscreen:
viewController.modalPresentationStyle = .fullScreen
navigationController.present(viewController, animated: animated)
}
}
public func pop(animated: Bool = true) {
navigationController.popViewController(animated: animated)
}
public func popToRoot(animated: Bool = true) {
navigationController.popToRootViewController(animated: animated)
}
open func dismiss(animated: Bool = true) {
navigationController.dismiss(animated: true) { [weak self] in
/// because there is a leak in UIHostingControllers that prevents from deallocation
self?.navigationController.viewControllers = []
}
}
}
struct MapView: View {
@EnvironmentObject var coordinator: Coordinator<MapRouter>
var body: some View {
NavigationView {
Button("Go to the city") {
coordinator.show(.city(named: "El Paso"))
}
}
}
}
I’m aware I can do it using NavigationPath but I need to support OS < 16 so that is not an option. Is it possible to do the push/pop/present using NavigationView & NavigationLink only?




