Skip to content

NavigationStack in SwiftUI Development

In this tutorial, we will dive into the world of NavigationStack, exploring how it enhances navigation in iOS, macOS, and iPadOS apps. We’ll provide a simple, yet comprehensive guide complete with code examples that you can test in Xcode.

Introduction to NavigationStack

NavigationStack is a SwiftUI view that manages a stack of views, much like a stack of cards. It displays a root view and enables you to present additional views over the root view. It’s part of the declarative SwiftUI framework, making it easier to manage the navigation flow of your app. Unlike the older NavigationView, NavigationStack offers a more intuitive and flexible way to handle navigation.

Implementing NavigationStack

Let’s create a basic two-view navigation: a Main view and a Detail view.

Step 1.1: Creating the Main View

First, we’ll start with our main view. This view will contain a button that, when tapped, navigates to the detail view.

import SwiftUI

struct MainView: View {
    var body: some View {
        NavigationStack {
            VStack {
                Text("Main View")
                    .font(.largeTitle)
                NavigationLink("Go to Detail View", destination: DetailView())
            }
        }
    }
}

In this code, NavigationStack is the container for our navigation views. The NavigationLink is used to link to our DetailView.

Step 1.2: Creating the Detail View

Next, we’ll create a simple detail view.

struct DetailView: View {
    var body: some View {
        Text("Detail View")
            .font(.largeTitle)
    }
}

The DetailView is straightforward, displaying only a text label.

Step 1.3: Running the App

Now, run the app in the simulator or on a real device. You should see the main view with a button. Tapping the button navigates to the detail view.

Advanced NavigationStack – Path

SwiftUI’s NavigationStack also supports programmatic navigation, where you can control the navigation flow using code.

Step 2.1: Adding Programmatic Navigation

We’ll start by defining SwiftUINavigationStackPath, which will act as our main view. This view will initiate navigation based on the path array.

struct SwiftUINavigationStackPath: View {
    @State private var path: [Int] = []

    var body: some View {
        NavigationStack(path: $path) {
            
            VStack {
                Button("Start") {
                    path.append(1) // Start with 1 to represent the first level of detail
                }
                .padding()
                .navigationDestination(for: Int.self) { int in
                    DetailView2(path: $path, count: int)
                }
                
                
                Text("Path contains \(path.count) items: \(path.map{ String($0) }.joined(separator: ","))")
            }
            .padding()
            .navigationTitle("Home")
        }
    }
}

Here, the Button in SwiftUINavigationStackPath is used to initiate navigation by appending an integer to the path. The .navigationDestination modifier handles navigation based on the current value in the path.

Step 2.2: Creating a Dynamic Detail View

Next, we create DetailView, which will present a new view each time the button is tapped, going “deeper” into the navigation stack.

struct DetailView2: View {
    @Binding var path: [Int]
    let count: Int

    var body: some View {
        VStack {
            Text("Level \(count)")
                .font(.largeTitle)
                .padding()
            Button("Go one Level deeper") {
                path.append(count + 1) // Increase the count to navigate deeper
            }
            .padding()
         
            
            Text("Path contains \(path.count) items: \(path.map{ String($0) }.joined(separator: ","))")
        }
        .padding()
        .navigationTitle("Detail Level \(count)")
        .toolbar {
            ToolbarItem(placement: .bottomBar) {
                Button("Pop to Root") {
                    path = []
                }
            }
        }
    }
}

In DetailView, each time the “Go deeper” button is tapped, we append a new integer to path, which represents a deeper level in the navigation stack. The “Pop to Root” button allows users to return to the root view by clearing the path.

Conclusion

NavigationStack in SwiftUI offers a powerful and flexible way to manage navigation in your iOS, macOS, and iPadOS apps. By dynamically managing the navigation path, you can create intuitive and user-friendly navigation flows in your applications. Experiment with this approach and adapt it to suit the specific needs of your app, exploring the various possibilities SwiftUI offers for innovative and efficient user interface design.

 

Back To Top