1

I would like to be able to popToRoot from my first tabItem (when im on page2 (from first tabItem) and tap twice on first tabItem when im on second tabItem) without having to use the NavigationViewKit package and only the new NavigationStack, is that possible?

My solution works fine but I would like to get rid of the NavigationViewKit package.

Any good advice\code example will be appreciated.

My code :

Home page

import SwiftUI
import NavigationViewKit

struct Home_V: View {
    @State var tabSelected: Int = 0
    @State private var tappedTwice: Bool = false
    
    // https://designcode.io/swiftui-handbook-tabbar-to-root-view
    var handler: Binding<Int> { Binding(
        get: { tabSelected },
        set: {
            if $0 == tabSelected {
                // print("tabSelected == \(tabSelected)")
                tappedTwice = true
            }
            tabSelected = $0
        }
    )}
    
    // https://github.com/fatbobman/NavigationViewKit
    @Environment(\.navigationManager) var nvmanager
    
    var body: some View {
        TabView(selection: handler) {
            NavigationStack {
                Page1()
                    .onChange(of: tappedTwice, perform: { tappedTwice in
                        guard tappedTwice else { return }
                        if tabSelected == 0 {
                            self.tappedTwice = false
                           nvmanager.wrappedValue.popToRoot(tag:"Page1", animated: true){}
                        }
                    })
            }
            .tabItem {
                Label("_HomeTitle", systemImage: "house")
                    .environment(\.symbolVariants, tabSelected == 0 ? .fill : .none)
            }
            .tag(0)
            .navigationViewStyle(StackNavigationViewStyle())
            
            NavigationStack {
                Page2()
            }
            .tabItem {
                Label("_MessagesTitle", systemImage: "envelope")
                    .environment(\.symbolVariants, tabSelected == 1 ? .fill : .none)
            }
            .tag(1)
            .navigationViewStyle(StackNavigationViewStyle())
            
        }

    }
}

Page1

import SwiftUI
import NavigationViewKit

struct Page1: View {
    var body: some View {
        VStack {
            Text("Page 1")
            NavigationLink {
                Page2()
            } label: {
                Text("Go to Page 2")
            }
        }
        .navigationViewManager(for: "Page1", afterBackDo: {print("Back to Page1")})
    }
}

Flincorp
  • 751
  • 9
  • 22
  • 1
    Does this answer your question? [NavigationStack not affected by EnvironmentObject changes](https://stackoverflow.com/questions/73723771/navigationstack-not-affected-by-environmentobject-changes) – Nirav D Sep 16 '22 at 17:26

1 Answers1

2

I got it!

Here is my test code :

import SwiftUI

class NavigationCoordinator: ObservableObject {
    @Published var path = NavigationPath()
    
    func popToRoot() {
        path.removeLast(path.count)
    }
}

struct Test_PopToRoot_NavigationStack: View {
    @State private var tabSelected: Int = 0
    @State private var tappedTwice: Bool = false
    
    @StateObject var navigationCoordinator = NavigationCoordinator()
    @StateObject var navigationCoordinator2 = NavigationCoordinator()
    
    
    // https://designcode.io/swiftui-handbook-tabbar-to-root-view
    var handler: Binding<Int> { Binding(
        get: { tabSelected },
        set: {
            if $0 == tabSelected {
                // print("tabSelected == \(tabSelected)")
                tappedTwice = true
            }
            tabSelected = $0
        }
    )}
    
    var body: some View {
        TabView(selection: handler) {
            NavigationStack(path: $navigationCoordinator.path) {
                VStack {
                    NavigationLink(value: 1) {
                        Test_PopToRoot_Tabview1()
                            .foregroundColor(.black)
                            .onChange(of: tappedTwice, perform: { tappedTwice in
                                guard tappedTwice else { return }
                                if tabSelected == 0 {
                                    self.tappedTwice = false
                                    print("Home tapped twice!!!")
                                    navigationCoordinator.popToRoot()
                                }
                            })
                    }
                }
            }
            .environmentObject(navigationCoordinator)
            .tabItem {
                Label("_HomeTitle", systemImage: "house")
                    .environment(\.symbolVariants, tabSelected == 0 ? .fill : .none)
            }
            .tag(0)
            .navigationViewStyle(StackNavigationViewStyle())
            
            NavigationStack(path: $navigationCoordinator2.path) {
                VStack {
                    NavigationLink(value: 1) {
                        Test_PopToRoot_Tabview2()
                            .foregroundColor(.black)
                            .onChange(of: tappedTwice, perform: { tappedTwice in
                                guard tappedTwice else { return }
                                if tabSelected == 1 {
                                    self.tappedTwice = false
                                    print("2nd Tab tapped twice!!!")
                                    navigationCoordinator2.popToRoot()
                                }
                            })
                    }
                }
            }
            .environmentObject(navigationCoordinator2)
            .tabItem {
                Label("_MessagesTitle", systemImage: "envelope")
                    .environment(\.symbolVariants, tabSelected == 1 ? .fill : .none)
            }
            .tag(1)
            .navigationViewStyle(StackNavigationViewStyle())
        }
    }
}


struct Test_PopToRoot_Tabview1: View {
    var body: some View {
        VStack {
               NavigationLink(value: 2) {
                   Text("Go To Page2")
                       .foregroundColor(.black)
               }
           }
           .navigationDestination(for: Int.self) { i in
               Test_PopToRoot_Page2()
           }
        .navigationTitle(Text("Tabview1"))
    }
}
Flincorp
  • 751
  • 9
  • 22
  • This will not animate the transition when popping with 2 or more items in the navigation path. Seems to be a bug (Xcode 14.1; iOS 16) – Martin Nov 06 '22 at 03:30