The classic way to navigate in a SwiftUI application is by using the NavigationStack with NavigationLink. In 99% of cases, this is sufficient. However, in some cases, we may need to navigate programmatically. How can we do that?
struct ContentView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
OnboardingUIView(path: $path)
.navigationDestination(for: String.self) { route in
switch route {
case "One":
OnboardingOneUIView(path: $path).navigationBarBackButtonHidden(true)
case "Two":
OnboardingTwoUIView(path: $path).navigationBarBackButtonHidden(true)
case "Three":
OnboardingThreeUIView(path: $path).navigationBarBackButtonHidden(true)
default:
EmptyView()
}
}
}
}
}
As we can see, we use a path passed to the NavigationStack. When something is added to the path, the destination changes. Let’s see what happens in the OnboardingUIView:
struct OnboardingUIView: View {
@Binding var path: NavigationPath
var body: some View {
VStack {
Text("Onboading")
Spacer()
HStack {
Spacer()
Button(action: {path.append("One")}) {
Text("Next")
.font(.title)
}.padding()
}
}
}
}
When we click the button, ‘One’ is added to the path. As a result, the NavigationStack moves to OnboardingOneUIView.

When we click the button, ‘One’ is added to the path. As a result, the NavigationStack moves to OnboardingOneUIView. Similarly, when ‘Two’ or ‘Three’ is added to the path, the NavigationStack navigates to OnboardingTwoUIView or OnboardingThreeUIView, respectively.
struct OnboardingOneUIView: View {
@Binding var path: NavigationPath
var body: some View {
VStack {
Text("Onboading One")
Spacer()
HStack {
Spacer()
Button(action: {path.append("Two")}) {
Text("Next")
.font(.title)
}.padding()
}
}
}
}
struct OnboardingTwoUIView: View {
@Binding var path: NavigationPath
var body: some View {
VStack {
Text("Onboading Two")
Spacer()
HStack {
Spacer()
Button(action: {path.append("Three")}) {
Text("Next")
.font(.title)
}.padding()
}
}
}
}
struct OnboardingThreeUIView: View {
@Binding var path: NavigationPath
var body: some View {
VStack {
Text("Onboading Three")
Spacer()
HStack {
Spacer()
Button(action: {}) {
Text("Next")
.font(.title)
}.padding()
}
}
}
}
In this way, we can navigate using the button, but we can also perform some actions and then decide whether to move to the next screen or not.
Leave a Reply