SALE ENDS TODAY: Save 50% on all Swift books and bundles! >>

How to create views in a loop using ForEach

Paul Hudson    @twostraws   

Fully updated for Xcode 11.2

You will commonly find that you want to loop over a sequence to create views, and in SwiftUI that’s done using ForEach.

Important: It’s easy to look at ForEach and think it’s the same as the forEach() method on Swift’s sequences, but this is not the case as you’ll see.

ForEach in SwiftUI is a view struct in its own right, which means you can return it directly from your view body if you want. You provide it an array of items, and you may also need to tell SwiftUI how it can identify each of your items uniquely so it knows how to update them when values change. You also pass it a closure to run to create a view for each item in the loop.

For simple loops over ranges, you can pass the range directly into ForEach and tell Swift to use each number as the unique identifier for the items. For example, this counts from 10 down to 1 then adds a message at the end:

VStack(alignment: .leading) {
    ForEach((1...10).reversed(), id: \.self) {
        Text("\($0)…")
    }

    Text("Ready or not, here I come!")
}

The .id(: \.self) part is required so that SwiftUI can identify each element in the array uniquely – it means that if you add or remove an item, SwiftUI knows exactly which one.

You can use this approach to create loops of any type. For example, this code creates an array of three colors, loops over them all, and creates text views using each color name and color value:

struct ContentView: View {
    let colors: [Color] = [.red, .green, .blue]

    var body: some View {
        VStack {
            ForEach(colors, id: \.self) { color in
                Text(color.description.capitalized)
                    .padding()
                    .background(color)
            }
        }
    }
}

Using \.self tells Swift each item is uniquely identified using its own value. So, if you have have the array [1, 2, 3] and identify each value by \.self it means the first item has the identifier 1, the second 2, and the third 3.

If you have custom types in your array, you should use id: with whatever property inside your type identifies it uniquely. For example, here’s a struct to store test results like this:

struct Result {
    var id = UUID()
    var score: Int
}

That has an id property with a UUID, which mean it’s guaranteed to be unique – perfect for our purposes. If we wanted to loop over an array of results, creating a text view showing each result in a VStack, then we’d use this:

struct ContentView: View {
    let results = [Result(score: 8), Result(score: 5), Result(score: 10)]

    var body: some View {
        VStack {
            ForEach(results, id: \.id) { result in
                Text("Result: \(result.score)")
            }
        }
    }
}

That tells SwiftUI it can distinguish between views inside the ForEach by looking at their id property.

As an alternative, if you make Result conform to Identifiable protocol you can just write ForEach(results). Conforming to this protocol means adding an id property that uniquely identifies each object, which in our case we already have. So, this code achieves the same result:

struct Result: Identifiable {
    var id = UUID()
    var score: Int
}

struct ContentView: View {
    let results = [Result(score: 8), Result(score: 5), Result(score: 10)]

    var body: some View {
        VStack {
            ForEach(results) { result in
                Text("Result: \(result.score)")
            }
        }
    }
}

SPONSORED Instabug helps you identify and resolve severe crashes quickly. You can retrace in-app events and know exactly which line of code caused the crash along with environment details, network logs, repro steps, and the session profiler. Ask more questions or keep users up-to-date with in-app replies straight from your dashboard. Instabug takes data privacy seriously, so no one sees your data but you! See more detailed features comparison and try Instabug's crash reporting SDK for free.

Save 50% on all books and bundles

The biggest ever Hacking with Swift sale is now on, letting you save 50% on all books and bundles. Learn something new with Swift and enjoy great savings while the sale lasts!

Click here to save 50% in our Black Friday sale!

Similar solutions…

BUY OUR BOOKS
Buy Pro Swift Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift (Vapor Edition) Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Server-Side Swift (Kitura Edition) Buy Beyond Code

Was this page useful? Let us know!

Average rating: 4.3/5