简体   繁体   中英

Unwind NavigationView to root when switching tabs in SwiftUI

I have an app with a few tabs, and on one of those there is a NavigationLink which nests a couple of times.

I want to be able to switch tabs, and when going back to the other tab to have unwound all links to the root view.

I have seen these: https://stackoverflow.com/a/67014642/1086990 and https://azamsharp.medium.com/unwinding-segues-in-swiftui-abdf241be269 but they seem to be focusing on unwinding when active on the view, not switching from it.

struct MyTabView: View {
 var body: some View {
  TabView {
   TabOne().tabItem { Image(systemName: "1.square") }
   TabTwo().tabItem { Image(systemName: "2.square") }
  }
 }
}

struct TabOne: View {
 var body: some View {
  Text("1")
 }
}

struct TabTwo: View {
 var body: some View {
  NavigationView {
   NavigationLink("Go to sub view") {
    TabTwoSub()
   }
  }
 }
}

struct TabTwoSub: View {
 var body: some View {
  Text("Tapping \(Image(systemName: "1.square")) doesnt unwind this view back to the root of the NavigationView")
   .multilineTextAlignment(.center)
 }
}

Maybe I've missed something fairly basic but nothing seems to come up from searches on unwinding views when switching tabs.

I tried using the NavigationLink(isActive: , destination: , label: ) from the other SO answer but couldn't get it working in the root MyTabView .

I thought about using UserDefaults to set a isActive bool state and if not try and unwind the navigation, but that didn't seem very swifty to do.

What is happening

在此处输入图像描述

You'll need to keep track of the tab selection in the parent view and then pass that into the child views so that they can watch for changes. Upon seeing a change in the selection, the child view can then reset a @State variable that change the isActive property of the NavigationLink .

class NavigationManager : ObservableObject {
    @Published var activeTab = 0
}

struct MyTabView: View {
    @StateObject private var navigationManager = NavigationManager()
    
    var body: some View {
        TabView(selection: $navigationManager.activeTab) {
            TabOne().tabItem { Image(systemName: "1.square") }.tag(0)
            TabTwo().tabItem { Image(systemName: "2.square") }.tag(1)
        }.environmentObject(navigationManager)
    }
}

struct TabOne: View {
    var body: some View {
        Text("1")
    }
}

struct TabTwo: View {
    @EnvironmentObject private var navigationManager : NavigationManager
    @State private var linkActive = false
    
    var body: some View {
        NavigationView {
            NavigationLink("Go to sub view", isActive: $linkActive) {
                TabTwoSub()
            }
        }.onChange(of: navigationManager.activeTab) { newValue in
            linkActive = false
        }
    }
}

struct TabTwoSub: View {
    var body: some View {
        Text("Tapping \(Image(systemName: "1.square")) doesnt unwind this view back to the root of the NavigationView")
            .multilineTextAlignment(.center)
    }
}

Note: this will result in a "Unbalanced calls to begin/end appearance transitions" message in the console -- in my experience, this is not an error and not something we have to worry about

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM