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.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

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!