SwiftUI Tutorial: Navigation
In this tutorial, you’ll use SwiftUI to implement the navigation of a master-detail app. You’ll learn how to implement a navigation stack, a navigation bar button, a context menu and a modal sheet. By Fabrizio Brancati.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
SwiftUI Tutorial: Navigation
30 mins
- Getting Started
- SwiftUI Basics in a Nutshell
- Declarative App Development
- Declaring Views
- Creating a Basic List
- The List id Parameter
- Starting Debug
- Navigating to the Detail View
- Creating a Navigation Link
- Revisiting Honolulu Public Artworks
- Creating Unique id Values With UUID()
- Conforming to Identifiable
- Showing More Detail
- Declaring Data Dependencies
- Guiding Principles
- Tools for Data Flow
- Adding a Navigation Bar Button
- Reacting to Artwork
- Adding a Context Menu
- Bonus Section: Eager Evaluation
- Where to Go From Here?
Bonus Section: Eager Evaluation
A curious thing happens when a SwiftUI app starts up: It initializes every object that appears in ContentView
. For example, it initializes DetailView
before the user taps anything that navigates to that view. It initializes every item in List
, regardles of whether the item is visible in the window.
This is a form of eager evaluation, and it’s a common strategy for programming languages. Is it a problem? Well, if your app has many items, and each item downloads a large media file, you might not want your initializer to start the download.
To simulate what’s happening, add an init()
method to Artwork
, so you can include a print
statement:
init(
artist: String,
description: String,
locationName: String,
discipline: String,
title: String,
imageName: String,
coordinate: CLLocationCoordinate2D,
reaction: String
) {
print(">>>>> Downloading \(imageName) <<<<<")
self.artist = artist
self.description = description
self.locationName = locationName
self.discipline = discipline
self.title = title
self.imageName = imageName
self.coordinate = coordinate
self.reaction = reaction
}
Now, run the app in simulator, and watch the debug console:
>>>>> Downloading 002_200105 <<<<< >>>>> Downloading 19300102 <<<<< >>>>> Downloading 193701 <<<<< >>>>> Downloading 193901-5 <<<<< >>>>> Downloading 195801 <<<<< >>>>> Downloading 198912 <<<<< >>>>> Downloading 196001 <<<<< >>>>> Downloading 193301-2 <<<<< >>>>> Downloading 193101 <<<<< >>>>> Downloading 199909 <<<<< >>>>> Downloading 199103-3 <<<<< >>>>> Downloading 197613-5 <<<<< >>>>> Downloading 199802 <<<<< >>>>> Downloading 198803 <<<<< >>>>> Downloading 199303-2 <<<<< >>>>> Downloading 19350202a <<<<< >>>>> Downloading 200304 <<<<<
It initialized all of the Artwork
items. If there were 1,000 items, and each downloaded a large image or video file, it could be a problem for a mobile app.
Here’s a possible solution: Move the download activity to a helper method, and call this method only when the item appears on the screen.
In Artwork.swift, comment out init()
and add this method:
func load() {
print(">>>>> Downloading \(self.imageName) <<<<<")
}
Back in ContentView.swift, modify the List
row:
Text("\(artwork.reaction) \(artwork.title)")
.onAppear { artwork.load() }
This calls load()
only when the row of this Artwork
is on the screen.
Run the app in simulator again:
>>>>> Downloading 002_200105 <<<<< >>>>> Downloading 19300102 <<<<< >>>>> Downloading 193701 <<<<< >>>>> Downloading 193901-5 <<<<< >>>>> Downloading 195801 <<<<< >>>>> Downloading 198912 <<<<< >>>>> Downloading 196001 <<<<< >>>>> Downloading 193301-2 <<<<< >>>>> Downloading 193101 <<<<< >>>>> Downloading 199909 <<<<< >>>>> Downloading 199103-3 <<<<< >>>>> Downloading 197613-5 <<<<< >>>>> Downloading 199802 <<<<<
This time, the last four items — the ones that aren’t visible — haven’t “downloaded”. Scroll the list to see their message appear in the console.
Where to Go From Here?
You can download the completed version of the project using the Download Materials button at the top or bottom of this tutorial.
In this tutorial, you used SwiftUI to implement the navigation of a master-detail app. You implemented a navigation stack, a navigation bar button, and a context menu, as well as a tab view. And you picked up one technique to prevent too-eager evaluation of your data items.
Apple’s WWDC sessions and SwiftUI tutorials are the source of everything, but you’ll also find the most up-to-date code in our book SwiftUI by Tutorials.
We hope you enjoyed this tutorial, and if you have any questions or comments, please join the forum discussion below!