0

I have:

TabView {
  ViewA()
  ViewB()
}

In ViewA I have a SubViewA() and

In ViewB I have a SubViewB()

How do I navigate from SubViewA() to SubViewB() using NavigationLink (or other solution) ? and have SubViewB() a back button that navigates to ViewB()

This is what I have so far:

ViewA()

struct ViewA: View {
  NavigationView {
    NavigationLink(destination: SubViewA()){}
  }
}

SubViewA()

struct SubViewA: View {
  NavigationLink(destination: SubViewB()){}
  .isDetailLink(false)
}

1 Answer 1

1

In SubViewA:

NavigationLink(destination: ViewB(toSubView: true)) {
    Text("Navigate")
}

In ViewB:

struct ViewB: View {
    @State var toSubView: Bool
    var body: some View {
        //Content...
        NabigationLink(destination: SubViewB(), isActive: $toSubView) {
        }.hidden()
    }
}

Or;

Now for multiple view just add your view to the Master Enum and the subviews to the Sub Enum. And for navigating use the navigate function with or without presentationMode.wrappedValue.dismiss(). Preview

 struct SubB: View {
    @Environment(\.presentationMode) var presentationMode
    @EnvironmentObject var navigation: Navigation
    var body: some View {
        VStack {
            Button(action: {
                withAnimation() {
                    navigation.navigate(to: .subViewC)
                    presentationMode.wrappedValue.dismiss()
                }
            }) {
                Text("Sub View C")
            }
        }.navigationBarTitle(Text("Sub B"))
    }
}


struct SubA: View {
    @EnvironmentObject var navigation: Navigation
    @Environment(\.presentationMode) var presentationMode
    var body: some View {
        VStack {
            Button(action: {
                withAnimation() {
                    navigation.navigate(to: .subViewB)
                    presentationMode.wrappedValue.dismiss()
                }
            }) {
                Text("Sub View B")
            }
        }.navigationBarTitle(Text("Sub A"))
    }
}

struct SubC: View {
    @EnvironmentObject var navigation: Navigation
    @Environment(\.presentationMode) var presentationMode
    var body: some View {
        VStack {
            Button(action: {
                withAnimation() {
                    navigation.navigate(to: .subViewA)
                    presentationMode.wrappedValue.dismiss()
                }
            }) {
                Text("Sub View A")
            }
        }.navigationBarTitle(Text("Sub C"))
    }
}

struct C: View {
    @EnvironmentObject var navigation: Navigation
    @Environment(\.presentationMode) var presentationMode
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: SubC(), tag: Sub.subViewC, selection: $navigation.subView) {
                    Text("Sub View C")
                }
            }.navigationBarTitle(Text("View C"))
        }
    }
}

struct A: View {
    @EnvironmentObject var navigation: Navigation
    var body: some View {
        NavigationView {
            VStack {
                Text("A")
                NavigationLink(destination: SubA(), tag: Sub.subViewA, selection: $navigation.subView) {
                    Text("SubView A")
                }
            }.navigationBarTitle(Text("View A"))
        }
    }
}

struct B: View {
    @EnvironmentObject var navigation: Navigation
    var body: some View {
        NavigationView {
            VStack {
                Text("B")
                NavigationLink(destination: SubB(), tag: Sub.subViewB, selection: $navigation.subView) {
                    Text("Sub B")
                }
            }.navigationBarTitle(Text("View B"))
        }
    }
}

struct Root: View {
    @EnvironmentObject var navigation: Navigation
    var body: some View {
        TabView(selection: $navigation.selected.int) {
            A()
                .tabItem {
                    Image(systemName: "capsule.portrait.fill")
                    Text("A")
                }.tag(Master.viewA.rawValue)
            B()
                .tabItem {
                    Image(systemName: "capsule.fill")
                    Text("B")
                }.tag(Master.viewB.rawValue)
            C()
                .tabItem {
                    Image(systemName: "capsule")
                    Text("C")
                }.tag(Master.viewC.rawValue)
        }
    }
}

class Navigation: ObservableObject {
    @Published var selected = Master.viewA
    @Published var subView: Sub?
    func navigate(to sub: Sub) {
        withAnimation() {
            guard let master = Master.init(rawValue: sub.int) else {return}
            selected = master
            subView = sub
        }
    }
}

enum Sub: Equatable {
    case subViewA
    case subViewB
    case subViewC
    var int: Int {
        switch self {
            case .subViewA = 0
            case .subViewB = 1
            case .subViewB = 2
           //here when adding subsubsubViews, it's value must be equal to it's master view i.e subsubViewA = 0
        }
    }
}

enum Master: Int, Equatable {
    case viewA = 0
    case viewB = 1
    case viewC = 2
    var int: Int {
        get {
            switch self {
                case .viewA:
                    return 0
                case .viewB:
                    return 1
                case .viewC:
                    return 2
            }
        }
        set {
            switch newValue {
                case 0:
                    self = .viewA
                case 1:
                    self = .viewB
                case 2:
                    self = .viewC
                default:
                    break
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

11 Comments

thanks but in the second solution, after navigating to the SubB, the tabview is still in A whereas it should in B
And if you wanna keep ViewA in SubViewA just remove presentationMode from the button
Yes, now it works. But I m still looking to make it closer to real use cases. Let's say you have SubSubSubView what's the best way to deal with this? keep passing the binding variables?
Also how do you solve this when you have 5 tabs? You declare 5 boolean variables??
Yes you can keep passing the binding variable or if in the future you have multiple variables it would be best to create an ObservableObject Class and use it as an environmentObject. Please accept it as a correct answer if you find it helpful!
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.