Skip to content

Instantly share code, notes, and snippets.

@benbacardi
Last active February 22, 2023 21:39
Show Gist options
  • Save benbacardi/92e6eec1d97204280f9dd3bc387a82f3 to your computer and use it in GitHub Desktop.
Save benbacardi/92e6eec1d97204280f9dd3bc387a82f3 to your computer and use it in GitHub Desktop.
Playing with "global router-style" navigation in SwiftUI
//
// ContentView.swift
// AppRouterPlayground
//
// Created by Ben Cardy on 22/02/2023.
//
import SwiftUI
enum Route: Hashable {
case firstDestination
case secondDestinationWithID(id: String)
}
@MainActor
class RoutePath: ObservableObject {
@Published var path: [Route] = []
public func navigate(to route: Route) {
path.append(route)
}
public func replace(with routes: [Route]) {
path = routes
}
}
struct FirstDestination: View {
@EnvironmentObject var routePath: RoutePath
var body: some View {
ScrollView {
Text("First Destination")
Button(action: {
routePath.navigate(to: .secondDestinationWithID(id: "ID 2"))
}) {
Text("Go To Second Destination")
}
}
.navigationTitle("First Destination")
}
}
struct SecondDestination: View {
@EnvironmentObject var routePath: RoutePath
let id: String
var body: some View {
ScrollView {
Text("Second Destination: \(id)")
Button(action: {
routePath.navigate(to: .firstDestination)
}) {
Text("Go To First Destination")
}
Button(action: {
routePath.replace(with: [.firstDestination, .firstDestination])
}) {
Text("Replace!")
}
}
.navigationTitle("Second \(id)")
}
}
@MainActor
extension View {
func withAppRouter() -> some View {
navigationDestination(for: Route.self) { destination in
switch destination {
case .firstDestination:
FirstDestination()
case let .secondDestinationWithID(id):
SecondDestination(id: id)
}
}
}
}
struct TabOne: View {
@StateObject private var routePath = RoutePath()
var body: some View {
NavigationStack(path: $routePath.path) {
ScrollView {
Text("Tab One")
Button(action: {
routePath.navigate(to: .firstDestination)
}) {
Text("Go To First Destination")
}
Button(action: {
routePath.navigate(to: .secondDestinationWithID(id: "ID 1"))
}) {
Text("Go To Second Destination")
}
}
.navigationTitle("Tab One")
.withAppRouter()
}
.environmentObject(routePath)
}
}
struct ContentView: View {
var body: some View {
TabView {
TabOne()
.tag(1)
.tabItem {
Label("Tab One", systemImage: "1.circle")
}
TabOne()
.tag(2)
.tabItem {
Label("Tab Two", systemImage: "2.circle")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment