Chapters

Hide chapters

SwiftUI by Tutorials

Fifth Edition · iOS 16, macOS 13 · Swift 5.8 · Xcode 14.2

Before You Begin

Section 0: 4 chapters
Show chapters Hide chapters

14. Lists
Written by Bill Morefield

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Most apps focus on displaying some type of data to the user. Whether upcoming appointments, past orders or new products, you must clearly show the user the information they come to your app for.

In the previous chapter, you saw a preview of iterating through data when displaying the flights for a day and allowing the user to interact with this data. In this chapter, you’ll dive deeper into the ways SwiftUI provides you to show a list of items to the user of your app.

Iterating Through Data

Open the starter project for this chapter and go to FlightList.swift in the FlightStatusBoard group. You’ll see a slightly different view than the one you created in the previous chapter. In place of List, which you’ll work with later in this chapter, you’ll start by examining ForEach.

SwiftUI uses ForEach as a fundamental element to loop over data. When you pass it a collection of data, it then creates multiple sub-views using a provided closure, one for each data item. ForEach works with any type of collected data. You can think of ForEach as the SwiftUI version of the for-in loop in traditional Swift code.

Run the app, tap Flight Status — and you’ll notice a mess.

Bad schedule
Bad schedule

Remember that ForEach operates as an iterator. It doesn’t provide any structure. As a result, you’ve created many views but not provided a layout for them. They’re all at the top level, not contained in anything else. SwiftUI tries to fit everything together, but the result is a mess. To fix both issues, add some structure around the loop:

ScrollView {
  VStack {
    ForEach(flights, id: \.id) { flight in
      NavigationLink(value: flight) {
        FlightRow(flight: flight)
      }
    }
    .navigationDestination(
      for: FlightInformation.self,
      destination: { flight in
        FlightDetails(flight: flight)
      }
    )
  }
}

You wrapped the ForEach loop inside a VStack — giving you a vertical stack of rows — and a ScrollView — that allows scrolling the rows since there’s more content than will fit onto the view. SwiftUI picks up that you’ve wrapped a VStack and applies vertical scrolling to match. If a line of text within the view became longer than the view’s width, SwiftUI wouldn’t automatically add horizontal scrolling.

Scrolled list
Scrolled list

You can override this default scrolling direction by passing in the desired scroll axes to ScrollView. To scroll the view in both directions, you would change the call to:

ScrollView([.horizontal, .vertical]) {

ScrollView provides a useful, general way to let a user browse through data that won’t fit onto a single screen.

Also note the id: parameter is passed a keypath to a property of the type in the array. This parameter hints that SwiftUI has expectations for the data sent to an iteration. In the next section, you’ll explore these expectations and make your data work more smoothly with SwiftUI.

Making Your Data Work Better With Iteration

The data passed into ForEach must provide a way to identify each element of the array as unique. In this loop, you use the id: parameter to tell SwiftUI to use the \.id property of FlightInformation as the unique identifier for each element in the array.

Dahs Wuzxfuutc uq Yaqapu hazg Ubuqhozeuxzi
Fojk Gehccaejx ib Kebova fanh Uficcuroepco

Improving Performance

When a VStack or HStack renders, SwiftUI creates all the cells at once. For a view such as this with only thirty rows, that probably doesn’t matter. For rows with hundreds of potential rows, that’s a waste of resources since most are not visible to the user. Using the Lazy versions of these stacks introduced in SwiftUI 2.0 (iOS 14, macOS 11, etc.) provides a quick performance improvement when iterating over large data sets.

Yozr nw meb
Vaxx cg wip

Setting the Scroll Position in Code

A major weakness of the first version of SwiftUI was the lack of a way to set the scrolling position programmatically. SwiftUI 2.0, introduced with iOS 14 and macOS Big Sur, added ScrollViewReader that allows setting the current position from code. You’ll use it to scroll the flight status list to the next flight automatically. Replace the current ScrollView with the following code:

Cobaviegitl Qacq we ybi Lagw Xbuwjs
Cohipuazing Vuwt ce sne Novb Dbopcd

Delu voux
Noti beax

Creating Lists

SwiftUI provides the List struct that does the heavy lifting for you and uses the platform-specific control to display the data. A List is a container much like a VStack or HStack that you can populate with static views, dynamic data or other iterative views.

Plepkf fikw
Ylemdr yesx

Building Search Results

To start building the search view, open SearchFlights.swift under the SearchFlights group. You’ll see view to allow the user to search for flights. However, the search functionality isn’t in place yet. In this section, you’re going to fix that.

Zox Noejhc Ciodb
Poh Maimsl Xieyy

Caojhkajz clazyxh
Nuuxhvivz zjuscmk

Building a Hierarchical List

SwiftUI added support for displaying hierarchical data in version 2.0. Much as the NavigationLink gives you a structure to organize views from general to more specific, a hierarchical list gives you an excellent way to display data that moves from general to more specific. In this section, you will update the search results into a hierarchical list that displays dates and then displays the flights for that date under it.

Qiihiwfqolok mufq
Xearerdhovov xarz

Laesuymfagiz zbeyfg hecb
Tiapeswqujez srebhs zeyw

Grouping List Items

A long list of data can be challenging for the user to read. Fortunately, the List view supports breaking a list into sections. Combining dynamic data and sections moves into some more complex aspects of displaying data in SwiftUI. In this section, you’ll separate flights into sections by date and add a header and footer to each section.

Qwiayof
Yfeawep

Key Points

  • A ScrollView wraps a view within a scrollable region that doesn’t affect the rest of the view.
  • The ScrollViewProxy lets you change the current position of a list from code.
  • SwiftUI provides two ways to iterate over data. The ForEach option loops through the data allowing you to render a view for each element.
  • A List uses the platform’s list control to display the elements in the data.
  • Data used with ForEach and List must provide a way to identify each element uniquely. You can do this by specifying an attribute that implements the Hashable protocol, have the object implement Hasbable and pass it to the id parameter or have your data implement the Identifiable protocol.
  • Building a hierarchical view requires a hierarchical data structure to describe how the view should appear.
  • You can split a List in Sections to organize the data and help the user understand what they see.
  • You can combine ForEach and List to create more complex data layouts. This method works well when you want to group data into sections.

Where to Go From Here?

For more on integrating navigation and views, look at SwiftUI Tutorial: Navigation at https://www.kodeco.com/5824937-swiftui-tutorial-navigation.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now