Skip to content

NavigationLink in SwiftUI

NavigationLink is a SwiftUI view that enables the transition between different parts of an app’s content hierarchy. It’s typically used within a NavigationStack (previously a NavigationView), allowing users to drill down into detailed views from a list or other selection mechanism.

Why Use NavigationLink?

  • Hierarchical Navigation: It’s ideal for apps requiring a drill-down interface where users select items from lists to view more details.
  • Accessibility: SwiftUI handles accessibility inherently, making your navigation accessible with minimal extra work.
  • Integration: Seamlessly integrates with SwiftUI’s declarative syntax, ensuring a smooth development experience.

NavigationLink helps users move smoothly from one view to another. With recent updates like NavigationStack and NavigationSplitView, SwiftUI gives developers even more power to create seamless and effective navigation in their apps. This guide will walk you through the advanced features of NavigationLink, showing you how to use these new tools to improve navigation in your apps.

Navigation using NavigationLink with NavigationStack

NavigationStack provides a straightforward way to manage a stack of views, allowing users to navigate forward and backward through an app’s content. Here’s how you can use NavigationLink within a NavigationStack to navigate to different color detail views.

struct ContentView: View {
  
    var body: some View {
        
        NavigationStack {
            List {
                NavigationLink(destination: { ColorView(color: .purple) }) {
                    
                    Label("Purple Passion", systemImage: "paintbrush.pointed")
                    
                }
                NavigationLink("Emerald Elegance") {
                    
                    ColorView(color: .green)
                    
                }
                NavigationLink(destination: { ColorView(color: .indigo) }) {
                    
                    Text("Indigo Inspiration")
                    
                }
            }
            .navigationTitle("Color Palette")
            
        }
        
    }
}

struct ColorView: View {
    let color: Color
    var body: some View {
        color
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

Creating a Presentation Link

SwiftUI now allows for navigation based on a presented data value, separating the view from the data to facilitate programmatic navigation. Here’s how to implement this using NavigationStack and .navigationDestination(for:destination:):

destination is a view builder that defines a view to display when the stack’s navigation state contains a value of type data. It takes an argument – the value of the data to present.

struct ContentView: View {
  
    var body: some View {
        
                NavigationStack {
                    List {
                        NavigationLink("Cerulean Sea", value: Color.blue)
                        NavigationLink("Golden Sunrise", value: Color.yellow)
                        NavigationLink("Crimson Night", value: Color.red)
                    }
                    .navigationDestination(for: Color.self) { color in
                        ColorView(color: color)
                    }
                    .navigationTitle("Scenic Colors")
                }

    }
}

struct ColorView: View {
    let color: Color
    var body: some View {
        color
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

Controlling Presentation Links Programmatically

To achieve programmatic navigation, SwiftUI allows the tracking of navigation state through binding to an array of items. This approach can dynamically modify the navigation stack:

struct ContentView: View {
    
    @State private var selectedColors: [Color] = []
  
    let colorNames: [Color: String] = [.red: "Red", .green: "Green", .blue: "Blue"] 
  
    var body: some View {

 NavigationStack(path: $selectedColors) {
                   VStack {
                       
                       Text("Selected Colors: \(selectedColors.map { color in colorNames[color, default: "Unknown"] }.joined(separator: ", "))")
                       
                       Button("Append Blue") {
                           selectedColors.append(.blue)
                       }
                       List {
                           NavigationLink("Verdant Green", value: Color.green)
                           NavigationLink("Ruby Red", value: Color.red)
                       }
                       .navigationDestination(for: Color.self) { color in
                           ColorView(selectedColors: $selectedColors, color: color)
                       }
                   }
                  
                   .navigationTitle("Jewel Tones")
               }
           }

    }

struct ColorView: View {
    
    let colorNames: [Color: String] = [.red: "Red", .green: "Green", .blue: "Blue"] 
    
    @Binding var selectedColors: [Color]
    
    let color: Color
    var body: some View {
        
        ZStack {
            
            color
                .frame(maxWidth: .infinity, maxHeight: .infinity)
            
            Text("Selected Colors: \(selectedColors.map { color in colorNames[color, default: "Unknown"] }.joined(separator: ", "))")
            
        }
    }
}

Coordinating NavigationLink with a List in NavigationSplitView

NavigationSplitView enhances iPad and Mac apps by allowing side-by-side content presentation. Here’s how to coordinate NavigationLink with a list selection:

struct ContentView: View {
    
    let colors: [Color] = [.orange, .pink, .purple]
    @State private var selection: Color?
    
    var body: some View {
   
        NavigationSplitView {
            List(colors, id: \.self, selection: $selection) { color in
                NavigationLink(color.description.capitalized, value: color)
            }
        } detail: {
            if let color = selection {
                ColorView(color: color)
            } else {
                Text("Select a Shade")
                    .font(.title)
            }
        }

    }
    
}


#Preview {
    SwiftUINavigationLink()
}


struct ColorView: View {
    
    let color: Color
    var body: some View {
        
        ZStack {
            
            color
                .frame(maxWidth: .infinity, maxHeight: .infinity)
            
        }
    }
}

Customizing NavigationLink

SwiftUI allows for extensive customization of NavigationLink, including the display of custom labels and the use of dynamic list data.

Using Custom Labels

Instead of default text, you can use custom views as labels for NavigationLink:

        NavigationStack {
          
            NavigationLink(destination: DetailView()) {
                HStack {
                    Image(systemName: "star.fill").foregroundColor(.yellow)
                    Text("Favorites")
                }
            }
       
        }

Conditional Navigation

Sometimes, navigation should occur based on certain conditions. Let’s implement it using path and NavigationLink.

struct FirstDetailView: View {
    var body: some View {
        Text("This is the First Detail View")
    }
}

struct SecondDetailView: View {
    var body: some View {
        Text("This is the Second Detail View")
    }
}

import SwiftUI

struct ContentView: View {
    @State private var navigationPath = NavigationPath()
    
    var body: some View {
        NavigationStack(path: $navigationPath) {
            VStack {
                Button("Go to First Detail") {
                    navigationPath.append(Destination.first)
                }
                
                Button("Go to Second Detail") {
                    navigationPath.append(Destination.second)
                }
            }
            .navigationDestination(for: Destination.self) { destination in
                switch destination {
                case .first:
                    FirstDetailView()
                case .second:
                    SecondDetailView()
                }
            }
        }
    }
}

In this guide, we’ve explored the power of SwiftUI’s NavigationLink and NavigationStack to create intuitive and dynamic navigation within your apps.

 

 

 

Back To Top