Posted in

Understanding ForEach in SwiftUI: Why You Need an id

SwiftUI foreach loop
Spread the love
Reading Time: 2 minutes

When you’re starting with SwiftUI, one of the first loops you’ll use is ForEach. It’s handy for creating repeated views, like a list of texts or buttons. But if you’ve tried using it, you might have run into a compiler error that looks confusing at first glance.

The Problem Code

Here’s the code many beginners write:

var body: some View {
    VStack {
        ForEach(1...5) { i in
            Text("i is \(i)")
        }
        Spacer()
    }
}

At first, this seems fine. We’re looping from 1 to 5 and creating a Text for each number. But SwiftUI gives us an error:

Type ‘Int’ does not conform to ‘Identifiable’

Why is that happening?

Why SwiftUI Needs an id

SwiftUI is declarative. That means instead of telling SwiftUI how to draw each frame, we describe what the UI should look like, and SwiftUI decides the most efficient way to update the screen.

To do this efficiently, SwiftUI must be able to track which view corresponds to which piece of data. If the data changes, SwiftUI needs a way to know:

  • Should it update an existing view?
  • Should it remove a view?
  • Should it create a new view?

This is where identifiers (id) come in. Each item in a ForEach needs a unique identifier so SwiftUI can match data to views during updates.

Fixing the Code with id: \.self

Since Int doesn’t conform to Identifiable, SwiftUI doesn’t know how to uniquely identify each number in the range. The fix is to explicitly provide an id:

var body: some View {
    VStack {
        ForEach(1...5, id: \.self) { i in
            Text("i is \(i)")
        }
        Spacer()
    }
}

Here’s what’s happening:

  • id: \.self tells SwiftUI: “Use the number itself as the unique identifier.”
  • Now SwiftUI knows that 1, 2, 3, etc. are unique and can track them properly.

✅ Problem solved!

When You Don’t Need id

If your data items are already identifiable, you don’t need to specify id. For example, consider a list of custom models:

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

let people = [
    Person(name: "Ali"),
    Person(name: "Sara")
]

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

Here, each Person already has a unique id, so SwiftUI automatically uses it to track the views.

Key Takeaways

  • SwiftUI needs identifiers to track items in a ForEach loop.
  • Int is not Identifiable, so you must provide id: \.self when looping over ranges like 1...5.
  • For custom models, make them conform to Identifiable or provide a unique property as the id.

Final Thoughts

If you’re new to SwiftUI, this can feel like an annoying detail. But once you understand why id is needed, it makes sense. SwiftUI isn’t just looping; it’s efficiently updating your UI by tracking which data belongs to which view.

So next time you see the error “Type ‘Int’ does not conform to ‘Identifiable’”, you’ll know exactly what to do!

I'm a passionate iOS Developer with over 8 years of experience building high-quality iOS apps using Objective-C, Swift, and SwiftUI. I created iostutor.com to share practical tips, tutorials, and insights for developers of all levels.

When I’m not coding, I enjoy exploring new technologies and writing content — from technical guides to stories and poems — with the hope that it might help or inspire someone, somewhere.

Leave a Reply

Your email address will not be published. Required fields are marked *