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
}
}
}
}