Give your simulator superpowers

RocketSim: An Essential Developer Tool
as recommended by Apple

SwiftUI Lists: Present rows of data explained with code examples

SwiftUI Lists allow you, as a developer, to present rows of data. It’s one of the most commonly used elements when building apps and the core of many navigation flows. Presenting rows of data is simply an implementation pattern you always need. You can use different list styles, change the background color, use sections, or add selection support.

If you’re new to Swift, I recommend reading my article on Swift Tutorials or how to get started with iOS App Development before continuing. Let’s dive in!

How to use SwiftUI Lists

The simplest example of a SwiftUI list would be with static data:

List {
    Text("Antoine")
    Text("Maaike")
    Text("Sep")
    Text("Jip")
}

This results in a view representing rows of data inside a scrollview:

SwiftUI Lists allow you to present rows of data.
SwiftUI Lists allow you to present rows of data.

However, you often want to dynamically populate the list based on a collection of data. For example, we can define a list of people and use that instead:

struct DynamicListView: View {
    
    var people: [Person] = [
        Person(name: "Antoine van der Lee", age: 34),
        Person(name: "Maaike", age: 6),
        Person(name: "Sep", age: 3),
        Person(name: "Jip", age: 1)
    ]
    
    var body: some View {
        List(people, id: \.name) { person in
            Text(person.name)
        }
    }
}

This results in the same list as shown in the previous example, but populated using a collection of Person elements.

Note that we’re using \.name as the unique identifier for each row of data. This could result in missing data if some people have the same name. Therefore, it’s better to make Person conform to the Identifiable protocol:

struct Person: Identifiable {
    let id = UUID()
    let name: String
    let age: Int
}

If you’re new to this protocol, I encourage you to read Identifiable protocol in SwiftUI explained with code examples.

Once done, you can update the SwiftUI list to remove the name unique identifier:

List(people) { person in
    Text(person.name)
}

This results in a clean list without the risk of showing duplicate rows.

Get the code examples for this article

Join 19,343 developers that stay up to date using my weekly newsletter and get access to code examples for all my articles:

Different kinds of SwiftUI List Styles

SwiftUI offers different list styles, including grouped, inset, and plain.
SwiftUI offers different list styles, including grouped, inset, and plain.

SwiftUI offers different default list styles. By default, the list style is set to automatic to adopt the platform’s default behavior and appearance based on the containment environment:

List(people) { person in
    Text(person.name)
}.listStyle(.automatic)

There are different list styles to pick from:

  • Automatic (DefaultListStyle)
    Describes a platform’s default behavior and appearance for a list.
  • Bordered (BorderedListStyle)
    Describes the behavior and appearance of a list with a standard border.
  • Carousel (CarouselListStyle)
    Represents the carousel list style.
  • Elliptical (EllipticalListStyle)
    Describes the behavior and appearance of an elliptical list.
  • Grouped (GroupedListStyle)
    Describes the behavior and appearance of a grouped list.
  • Inset (InsetListStyle)
    Describes the behavior and appearance of an inset list.
  • Inset Grouped (InsetGroupedListStyle)
    Describes the behavior and appearance of an inset grouped list.
  • Plain (PlainListStyle)
    Describes the behavior and appearance of a plain list.

Each style is defined by a struct as mentioned in the list. For example, you can apply the grouped list style using listStyle(.grouped) or by using listStyle(GroupedListStyle()). Static Member Lookup in Generic Contexts lets you find all available list styles.

Using sections inside a SwiftUI List

An everyday use case of SwiftUI lists is to combine sections with the grouped list style:

struct GroupedListView: View {
    
    var body: some View {
        List {
            Section {
                Text("Antoine")
                Text("Maaike")
            } header: {
                Text("Parents")
            } footer: {
                Text("End of parents section")
            }
            
            Section {
                Text("Sep")
                Text("Jip")
            } header: {
                Text("Kids")
            } footer: {
                Text("End of kids section")
            }
        }.listStyle(.grouped)
    }
}

The sections group the data visually and allow you create a better hierarchy. When using the sidebar list style, you can also make the section collapsible:

struct ExpandableSectionsListView: View {
    
    @State private var isExpanded = true
    
    var body: some View {
        List {
            Section(isExpanded: $isExpanded) {
                Text("Antoine")
                Text("Maaike")
                Text("Sep")
                Text("Jip")
            } header: {
                Text("Expandable section")
            }
        }.listStyle(.sidebar)
    }
}

Supporting selection in lists

You can use SwiftUI lists to enable the selection of data. It’s most common to do this using the edit mode, which can be enabled using the edit toolbar button:

struct SelectionListView: View {
    
    var people: [Person] = [
        Person(name: "Antoine van der Lee", age: 34),
        Person(name: "Maaike", age: 6),
        Person(name: "Sep", age: 3),
        Person(name: "Jip", age: 1)
    ]

    @State var selectedPeopleIdentifiers: Set<UUID> = []
    
    var body: some View {
        NavigationView {
            List(people, selection: $selectedPeopleIdentifiers) { person in
                Text(person.name)
            }
            .toolbar { EditButton() }
        }
        Text("Selected \(selectedPeopleIdentifiers.count) item(s)")
    }
}

This results in a view that shows an edit toolbar button and a multi-selection mode:

You can enable selection inside lists of data.
You can enable selection inside lists of data.

However, you might not want to use the edit button and still offer selection. For example, you might want to use an SF Symbol in case an item gets selected:

struct SelectionSFSymbolListView: View {
    
    var people: [Person] = [
        Person(name: "Antoine van der Lee", age: 34),
        Person(name: "Maaike", age: 6),
        Person(name: "Sep", age: 3),
        Person(name: "Jip", age: 1)
    ]

    @State var selectedPeopleIdentifiers: Set<UUID> = []
    
    var body: some View {
        List(people, selection: $selectedPeopleIdentifiers) { person in
            Label(person.name, systemImage: selectedPeopleIdentifiers.contains(person.id) ? "checkmark.circle" : "circle")
        }
        Text("Selected \(selectedPeopleIdentifiers.count) item(s)")
    }
}

Changing the list background color

When changing the background of a SwiftUI Lists, you’ll quickly notice it won’t be updating. The key solution here is to use a background combined with the scrollContentBackground modifier:

struct CustomBackgroundListView: View {
    var body: some View {
        List {
            Text("Antoine")
            Text("Maaike")
            Text("Sep")
            Text("Jip")
        }.background(Color.orange)
            .scrollContentBackground(.hidden)
    }
}

Once you’ve set the scroll content background to hidden, you can change the background to anything you want. In the above example, we’ve created a list with an orange background color:

You can use a custom list background color in SwiftUI once you've disabled the scroll content background.
You can use a custom list background color in SwiftUI once you’ve disabled the scroll content background.

Conclusion

SwiftUI Lists allow you to present rows of data using different list styles. You can enable selection using edit mode or by using a custom selection representation with SF Symbols. Combined with a grouped list style, sections allow you to optimize the data hierarchy.

If you want to improve your SwiftUI knowledge, even more, check out the SwiftUI category page. Feel free to contact me or tweet me on Twitter if you have any additional tips or feedback.

Thanks!

 
Antoine van der Lee

Written by

Antoine van der Lee

iOS Developer since 2010, former Staff iOS Engineer at WeTransfer and currently full-time Indie Developer & Founder at SwiftLee. Writing a new blog post every week related to Swift, iOS and Xcode. Regular speaker and workshop host.

Are you ready to

Turn your side projects into independence?

Learn my proven steps to transform your passion into profit.