Learn how to work with Xcode Previews in SwiftData App. SwiftData in combination with SwiftUI…
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.