I have a NavigationView
and it has 3 views I want to navigate to successively. Each view has a NavigationLink
within it. Ideally, I want:
View 1 -> View 2 -> View 3
But what I get is: View 1 -> View 2 -> View 3 (1sec) -> View 1
I am using the tagged selection method for the NavigationLink
, and the selection is from a @Published
EnvironmentObject
.
Here's the code:
import SwiftUI
struct ContentView: View {
@EnvironmentObject var viewModel: ViewModel
var body: some View {
VStack {
NavigationLink(destination: secondPage(), tag: "View 2", selection: $viewModel.selection) {
Button(
action: {
viewModel.selection = "View 2"
}, label: {
Text("view 2")
}
)
.navigationTitle("View 1")
}
.isDetailLink(false)
}
}
}
struct secondPage: View {
@EnvironmentObject var viewModel: ViewModel
var body: some View {
NavigationLink(destination: thirdPage(), tag: "View 3", selection: $viewModel.selection) {
Button(
action: {
viewModel.selection = "View 3"
},
label: {
Text("View 3")
}
)
.navigationTitle("View 2")
}
.isDetailLink(false)
}
}
struct thirdPage: View {
var body: some View {
VStack {
Text("third page")
}
.navigationTitle("View 3")
}
}
class ViewModel: ObservableObject {
@Published var selection: String? = nil
}
import SwiftUI
@main
struct testApp: App {
@StateObject var viewModel = ViewModel()
var body: some Scene {
WindowGroup {
NavigationView {
ContentView()
}
.navigationViewStyle(StackNavigationViewStyle())
.environmentObject(viewModel)
}
}
}
I use a button and the viewModel because in my real code I need the code to perform an action.
Help would be so appreciated!
CodePudding user response:
Welcome to StackOverflow! The problem you are having is very similar to this question, but you are using a different mechanism. The reason for the pop back is that you are using the same variable to handle both NavigationLinks
, so, instead of:
View 1 -> View 2 -> View 3
what is actually happening is:
View 1(viewModel.selection = "View 2") -> View 2
Then, when you try to navigate again:
View 2(viewModel.selection = "View 3")
You are actually changing your original link to
View 1(viewModel.selection = "View 3") -> View 2
as well. The OS gets confused and pops back to the first link(SecondPage
). To fix it, simply use multiple variables to keep the navigation state:
struct ContentView: View {
@EnvironmentObject var viewModel: PageViewModel
var body: some View {
VStack {
NavigationLink(destination: secondPage(), tag: "View 2", selection: $viewModel.selection2) {
Button(
action: {
viewModel.selection2 = "View 2"
}, label: {
Text("view 2")
}
)
.navigationTitle("View 1")
}
.isDetailLink(false)
}
}
}
struct secondPage: View {
@EnvironmentObject var viewModel: PageViewModel
var body: some View {
NavigationLink(destination: thirdPage(), tag: "View 3", selection: $viewModel.selection3) {
Button(
action: {
viewModel.selection3 = "View 3"
},
label: {
Text("View 3")
}
)
.navigationTitle("View 2")
}
.isDetailLink(false)
}
}
struct thirdPage: View {
var body: some View {
VStack {
Text("third page")
}
.navigationTitle("View 3")
}
}
class PageViewModel: ObservableObject {
@Published var selection2: String? = nil
@Published var selection3: String? = nil
}