SwiftUI Blog

Mastering SwiftUI: Your Guide to Building Beautiful, Intuitive Apps.

Navigate Programmatically


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

Your email address will not be published. Required fields are marked *