SwiftUI: попытка создать универсальный маршрутизатор с NavigationView/NavigationLink

Я пытаюсь портировать UIKit приложение в UISwift. В этом приложении я создал общий маршрутизатор, который работает следующим образом:

enum Route {
    case home
    case settings
    case specific(setting: Int)

    var viewController: UIViewController {
        switch self {
        case .home:
            return HomeVC {
                Router.to(.settings)
            }
        case .settings:
            return SettingsVC { specificSetting in
                Router.to(.specific(setting: specificSetting))
            }
        case .specific(let setting):
            return SpecificSettingVC(setting)
        }
    }
}

Связанные viewControllers:

class HomeVC: UIViewController {
    var toSettings: () -> Void
    
    init(_ toSettings: @escaping () -> Void) {
        self.toSettings = toSettings
        super.init(nibName: "HomeVC", bundle: .main)
    }
    
    required init?(coder: NSCoder) {
        fatalError()
    }
}

class SettingsVC: UIViewController {
    var toSpecificSetting: (Int) -> Void
    
    init(_ specificSetting: @escaping (Int) -> Void) {
        self.toSpecificSetting = specificSetting
        super.init(nibName: "SettingsVC", bundle: .main)
    }
    
    required init?(coder: NSCoder) {
        fatalError()
    }
}

class SpecificSettingVC: UIViewController {
    private let settingIndex: Int
    
    init(_ index: Int) {
        self.settingIndex = index
        super.init(nibName: "SpecificSettingVC", bundle: .main)
    }
    
    required init?(coder: NSCoder) {
        fatalError()
    }
}

А роутер просто:

struct Router {
    static func to(_ route: UIRoute) {
        // In this function I find the current navigationController 
        // and call .pushViewController(route.viewController, animated: true)
    }
}

Мне понравилось, потому что это Route enum немного походил на карту сайта, быстро показывая мне все маршруты в приложении.

Я хотел бы сделать что - то подобное в SwiftUI, благодаря этой обучающей программе мне удалось интересный результат:

Перечисление маршрута:

enum Route {
    case blue
    case red
    var view: some View {
        VStack {
            switch self {
            case .blue:
                BlueView()
            case .red:
                RedView()
            }
        }
    }
}

Маршрутизатор:

class Router: ObservableObject {
    let objectWillChange = PassthroughSubject<Router, Never>()
    var currentRoute: Route = .blue {
        didSet {
            withAnimation {
                objectWillChange.send(self)
            }
        }
    }
}

Вид роутера:

struct RouterView: View {
    @EnvironmentObject var router: Router
    
    var body: some View {
        VStack {
            switch router.currentRoute {
            case .blue:
                BlueView(toRed: {
                    router.currentRoute = .red
                })
            case .red:
                RedView(back: {
                    router.currentRoute = .blue
                })
            }
        }
    }
}

Конечно приложение:

@main
struct MainApp: App {
    var body: some Scene {
        WindowGroup {
            RouterView()
                .environmentObject(ViewRouter())
        }
    }
}

И, например, BlueView:

struct BlueView: View {
    @EnvironmentObject var viewRouter: ViewRouter
    var toRed: () -> Void
    
    var body: some View {
        ZStack {
            Color.blue
            Button(action: {
                toRed()
            }, label: {
                Text("Tap me!")
                    .foregroundColor(.white)
            })
        }
    }
}

Хотя это работает нормально, это только заменяет представление, содержащееся в RouterView. Мне было интересно, могу ли я сделать что-то подобное, используя NavigationViews и NavigationLinks. Но я действительно не знаю, что делать и с чего начать.

Любая идея и помощь будут оценены.

Спасибо!

0 ответов

Другие вопросы по тегам