Router-SwiftUIWorkaround
Workaround for https://www.swiftuiseries.com/workarounds
2022-05-24.12.52.00.mov
About
SwiftUI does not allow programmable screen navigation out of the box, has many bugs and limited screen manipulation capabilities. This repository provides a workaround to use routing programmatically.
Steps to use
- Configure routes Use enum for routes and dont forget to choose screens with NavigationView!
enum ScreenRoute: ScreenProtocol {
case start
case navigator
case fullScreen
case sheetScreen
var embedInNavView: Bool {
switch self {
case .start, .sheetScreen:
return true
case .navigator, .fullScreen:
return false
}
}
}
- Create router factory. This class maps routes and creates views.
class ScreenRouterFactory: RouterFactory {
@ViewBuilder func makeBody(for screen: ScreenRoute) -> some View {
switch screen {
case .start:
StartingView()
case .navigator:
RoutesView()
case .fullScreen:
FullScreenView()
case .sheetScreen:
SheetView()
}
}
}
- (? optional) Create typealias for easy naming Routers.
typealias ScreenRouter = Router<ScreenRoute, ScreenRouterFactory>
- Create Router instance. You can create in Views, ViewModels or use in DI. Don’t forget to use @StateObject or similar wrappers in views for re-render
let screenRouter = ScreenRouter(rootScreen: .start, factory: ScreenRouterFactory())
- Use it! Start routing with start method. In this example EnvObject used:
struct MainView: View {
@EnvironmentObject var screenRouter: ScreenRouter
var body: some View {
screenRouter.start()
}
}
- Available Router’s methods:
func start() -> some View
func presentSheet(_ screen: ScreenType)
func dismissLast()
func navigateTo(_ screen: ScreenType)
func presentFullScreen(_ screen: ScreenType)
func popToRoot()