SwiftUI’s NavigationStack
shows a navigation bar at the top of our views, but also does something else: it lets us push views onto a view stack. In fact, this is really the most fundamental form of iOS navigation – you can see it in Settings when you tap Wi-Fi or General, or in Messages whenever you tap someone’s name.
This view stack system is very different from the sheets we’ve used previously. Yes, both show some sort of new view, but there’s a difference in the way they are presented that affects the way users think about them.
Let’s start by looking at some code so you can see for yourself – we could show a simple text view inside a navigation stack like this:
struct ContentView: View {
var body: some View {
NavigationStack {
Text("Tap Me")
.navigationTitle("SwiftUI")
}
}
}
That text view is just static text; it’s not a button with any sort of action attached to it, despite what its title says. We’re going to make it so that when the user taps on it we present them with a new view, and that’s done using NavigationLink
: give this a destination and something that can be tapped, and it will take care of the rest.
One of the many things I love about SwiftUI is that we can use NavigationLink
with any kind of destination view. Yes, we can design a custom view to push to, but we can also push straight to some text.
To try this out, change your view to this:
NavigationStack {
NavigationLink("Tap Me") {
Text("Detail View")
}
.navigationTitle("SwiftUI")
}
Now run the code and see what you think. You will see that “Tap Me” now looks like a button, and tapping it makes a new view slide in from the right saying “Detail View”. Even better, you’ll see that the “SwiftUI” title animates down to become a back button, and you can tap that or swipe from the left edge to go back.
If you want something other than a simple text view as your label, you can use two trailing closures with your NavigationLink
. For example, we could make a label out of several text views and an image:
NavigationStack {
NavigationLink {
Text("Detail View")
} label: {
VStack {
Text("This is the label")
Text("So is this")
Image(systemName: "face.smiling")
}
.font(.largeTitle)
}
}
So, both sheet()
and NavigationLink
allow us to show a new view from the current one, but the way they do it is different and you should choose them carefully:
NavigationLink
is for showing details about the user’s selection, like you’re digging deeper into a topic.sheet()
is for showing unrelated content, such as settings or a compose window.The most common place you see NavigationLink
is with a list, and there SwiftUI does something quite marvelous.
Try modifying your code to this:
NavigationStack {
List(0..<100) { row in
NavigationLink("Row \(row)") {
Text("Detail \(row)")
}
}
.navigationTitle("SwiftUI")
}
When you run the app now you’ll see 100 list rows that can be tapped to show a detail view, but you’ll also see gray disclosure indicators on the right edge. This is the standard iOS way of telling users another screen is going to slide in from the right when the row is tapped, and SwiftUI is smart enough to add it automatically here. If those rows weren’t navigation links – if you comment out the NavigationLink
line and its closing brace – you’ll see the indicators disappear.
SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure and A/B test your entire paywall UI without any code changes or app updates.
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.