Skip to content

Instantly share code, notes, and snippets.

@JagCesar
Created July 3, 2024 17:57
Show Gist options
  • Save JagCesar/17fa60e25ca196f5cb171d518157ee67 to your computer and use it in GitHub Desktop.
Save JagCesar/17fa60e25ca196f5cb171d518157ee67 to your computer and use it in GitHub Desktop.
SwiftUI view that pushes twice on iOS 18 b2
//
// ContentView.swift
// dev
//
// Created by César Pinto Castillo on 2024-07-03.
//
import SwiftUI
struct ContentView: View {
@State private var pathManager = PathManager()
@State private var selectedTab: Tabs = .first
var body: some View {
TabView(selection: $selectedTab) {
Tab("First", systemImage: "circle", value: .first) {
NavigationStack(path: $pathManager.firstPath) {
NavigationLink(value: NavigationPath.third) {
Text("Open Third")
}
.navigationDestination()
}
}
Tab("Second", systemImage: "square", value: .second) {
NavigationStack(path: $pathManager.secondPath) {
NavigationLink(value: NavigationPath.fourth) {
Text("Open Fourth")
}
.navigationDestination()
}
}
}
}
}
enum Tabs {
case first
case second
}
enum NavigationPath {
case third
case fourth
}
extension View {
func navigationDestination() -> some View {
self.navigationDestination(for: NavigationPath.self) { path in
switch path {
case .fourth:
Text("Fourth")
case .third:
Text("Third")
}
}
}
}
@Observable
class PathManager {
var firstPath: [NavigationPath] = []
var secondPath: [NavigationPath] = []
}
#Preview {
ContentView()
}
@claesjacobsson
Copy link

claesjacobsson commented Jul 3, 2024

However, in a more real-world like example where views are separated and the PathManager passed as an environment object, it seems to work...

struct ContentView: View {
    private var pathManager = PathManager()
    @State private var selectedTab: Tabs = .first

    var body: some View {
        TabView(selection: $selectedTab) {
            Tab("First", systemImage: "circle", value: .first) {
                FirstScreen()
            }
            Tab("Second", systemImage: "square", value: .second) {
                SecondScreen()
            }
        }
        .environment(pathManager)
    }
}

enum Tabs {
    case first
    case second
}

enum AppScreen {
    case third
    case fourth
}

extension View {
    func navigationDestination() -> some View {
        self.navigationDestination(for: AppScreen.self) { path in
            switch path {
            case .fourth:
                Text("Fourth")
            case .third:
                Text("Third")
            }
        }
    }
}

@Observable
class PathManager {
    var firstPath: [AppScreen] = []
    var secondPath: [AppScreen] = []
}

#Preview {
    ContentView()
}


struct FirstScreen: View {
    @Environment(PathManager.self) private var pathManager

    var body: some View {
        @Bindable var pathManager = pathManager
        NavigationStack(path: $pathManager.firstPath) {
            NavigationLink(value: AppScreen.third) {
                Text("Open Third")
            }
            .navigationDestination()
        }
    }
}

struct SecondScreen: View {
    @Environment(PathManager.self) private var pathManager

    var body: some View {
        @Bindable var pathManager = pathManager
        NavigationStack(path: $pathManager.secondPath) {
            NavigationLink(value: AppScreen.fourth) {
                Text("Open Fourth")
            }
            .navigationDestination()
        }

    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment