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
. Но я действительно не знаю, что делать и с чего начать.
Любая идея и помощь будут оценены.
Спасибо!