Using enumerated() with SwiftUI List and ForEach to show item numbers

When displaying items in SwiftUI, we sometimes want to include their position in the sequence, for example, to show a list of instructions or ranked results. A common way to achieve this is by calling enumerated() on the collection. This returns an EnumeratedSequence, which is a sequence of (offset, element) pairs, where offset is a counter starting from zero and element is the corresponding value from the original collection.

Until recently, enumerated() wasn’t directly compatible with ForEach or List in SwiftUI, because the result did not conform to RandomAccessCollection. As a workaround, we had to wrap the sequence in an array.

RecipeStepsView: View {
    let steps = [
        "Chop lettuce, tomatoes, and cucumber.",
        "Drizzle with olive oil and lemon juice.",
        "Toss gently and serve."
    ]
    
    var body: some View {
        VStack(alignment: .leading) {
            ForEach(
                Array(steps.enumerated()), id: \.element
            ) { offset, step in
                Text("\(offset + 1). \(step)")
            }
        }
    }
}

As of Swift 6.2 and iOS 26, this extra step is no longer required. Proposal SE-0459 adds Collection, RandomAccessCollection, and BidirectionalCollection conformance to EnumeratedSequence when the base collection supports those protocols.

ForEach(
    steps.enumerated(), id: \.element
) { offset, step in
    Text("\(offset + 1). \(step)")
}

It’s important to note that the offset in EnumeratedSequence is a counter and should not be used as an index to access elements from the original collection. While it may appear to work when the base collection is zero-based and uses integer indices, this assumption breaks down in other scenarios, for example, when iterating over a SubSequence or any collection that does not start at zero. For more details and recommended approaches, see my other post: Iterate over items and indices in Swift collections.

Another important point to consider is that neither offset nor an index should be used as the id in ForEach unless the collection is immutable and the ordering is guaranteed to remain stable. In dynamic collections where elements can be added, removed, or reordered, such as in user-editable lists, using a counter or index as the identifier can result in incorrect view updates and animations. In these cases, a stable and unique identifier should be used instead, either by conforming the element type to Identifiable or by supplying a unique key path.

struct Task: Identifiable {
    var id = UUID()
    var title: String
}

struct TaskListView: View {
    @State private var tasks = [
        Task(title: "Buy vegetables"),
        Task(title: "Prep dressing"),
        Task(title: "Set the table")
    ]
    
    var body: some View {
        List {
            ForEach(
                tasks.enumerated(),
                id: \.element.id
            ) { offset, task in
                Text("\(offset + 1). \(task.title)")
            }
            .onDelete { indices in
                tasks.remove(atOffsets: indices)
            }
        }
    }
}

This pattern keeps the display numbering from enumerated() while maintaining stable identity through the task’s id. By decoupling numbering from identity, it ensures correct behavior as the data changes.

If you want to build a strong foundation in SwiftUI, my new book SwiftUI Fundamentals takes a deep dive into the framework’s core principles and APIs to help you understand how it works under the hood and how to use it effectively in your projects.

For more resources on Swift and SwiftUI, check out my other books and book bundles.

SwiftUI Fundamentals by Natalia Panferova book coverSwiftUI Fundamentals by Natalia Panferova book cover

Deepen your understanding of SwiftUI!$35

The essential guide to SwiftUI core concepts and APIs

SwiftUI Fundamentalsby Natalia Panferova

  • Explore the key APIs and design patterns that form the foundation of SwiftUI
  • Develop a deep, practical understanding of how SwiftUI works under the hood
  • Learn from a former Apple engineer who worked on widely used SwiftUI APIs

Deepen your understanding of SwiftUI!

The essential guide to SwiftUI core concepts and APIs

SwiftUI Fundamentals by Natalia Panferova book coverSwiftUI Fundamentals by Natalia Panferova book cover

SwiftUI Fundamentals

by Natalia Panferova

$35