Give your simulator superpowers

RocketSim: An Essential Developer Tool
as recommended by Apple

SwiftUI ForEach Explained with Code Examples

If you’re building dynamic lists or repeating UI components in SwiftUI, there’s a high chance you’re already using the SwiftUI ForEach view element. It’s a powerful, yet sometimes misunderstood, view element in SwiftUI.

This article will help you understand how ForEach works and when and how to use it. We’ll also dive into index-based iteration and how the Identifiable protocol can help you out.

What is SwiftUI ForEach?

The SwiftUI ForEach view element allows you to iterate over a collection and generate a view for each.
The SwiftUI ForEach view element allows you to iterate over a collection and generate a view for each.

The SwiftUI ForEach view allows you to iterate over a collection and generate views for each element. It’s especially useful when working with ListLazyVStack, or any container that supports multiple children.

struct ContentView: View {
    let names = ["Antoine", "Maaike", "Sep", "Jip"]

    var body: some View {
        ForEach(names, id: \.self) { name in
            Text(name)
        }
    }
}

In the above example, we iterate over all names in the collection by using \.self as the identifier since String conforms to Hashable. For custom types, it’s better to provide a unique identifier via the Identifiable protocol.

Get the code examples for this article

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

ForEach with Identifiable Data

Iterating over a collection using the Identifiable protocol is the cleanest approach. It allows us to remove the \.self identifier and rely on the id property requirement of the Identifiable protocol instead:

struct ContentView: View {
    let people = [
        Person(id: UUID(), name: "Antoine"),
        Person(id: UUID(), name: "Maaike")
    ]

    var body: some View {
        ForEach(people) { person in
            Text(person.name)
        }
    }
}

Using Identifiable helps SwiftUI track view identity across state updates and avoid unnecessary redraws.

Using ForEach in Lists

When used inside a List, the SwiftUI ForEach view becomes essential for rendering dynamic rows:

List {
    ForEach(people) { person in
        HStack {
            Image(systemName: "person")
            Text(person.name)
        }
    }
}

Iterating with an Index

By using an enumerated array, you can iterate over items and their indexes:

ForEach(Array(people.enumerated()), id: \.offset) { index, person in
    Text("Index \(index): \(person.name)")
}

This can occasionally be useful if you need to have the index at hand while performing index-based view styling, for example.

Conclusion

SwiftUI ForEach is an essential part of building dynamic interfaces. It’s recommended to use it in combination with the Identifiable protocol, but using the id parameter should work in most cases too. You can use an enumerated array if you also need to have the index for each item while iterating.

If you’re interested in learning more about other SwiftUI elements, I recommend the following articles:

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.