TechnologiesSwiftUILists and Collections

IndexedIdentifierCollection struct

iOSmacOStvOSwatchOSvisionOSiOS 16.0+✓ renders

A collection wrapper that iterates over the indices and identifiers of a

How it works

IndexedIdentifierCollection is the collection SwiftUI produces when you need to drive a list or ForEach from values that don't carry their own identity. By pairing each element with a stable identifier derived from its position, it gives the framework a reliable way to track, diff, and animate rows even when the underlying data are plain values like strings or numbers. Reach for it whenever you have an ordered sequence without a natural identity key and want SwiftUI to treat each slot as a distinct, persistent item.

  1. Supply position as the identity

    The core idea is to project each element together with its index so SwiftUI has something stable to key on. In the example, Array(fruits.enumerated()) turns the bare fruits array into index/value pairs, which is exactly the indexed shape IndexedIdentifierCollection represents.

  2. Select the identifier with the id parameter

    The id: argument tells the collection which property uniquely identifies each row. Here id: \.offset names the enumerated offset as the identifier, so each fruit is tracked by its ordinal position rather than by its text, anchoring identity even if two elements share the same value.

  3. Receive both index and element in the row closure

    Because identity is built from the index, each iteration hands you the position alongside the value. The trailing closure binds index, fruit, letting the row use the position directly—Text("\(index + 1).") renders a running number while Text(fruit) shows the element itself.

  4. Plug the collection into a List

    An IndexedIdentifierCollection is consumed by identity-aware containers like List and ForEach. The List(...) initializer takes the indexed pairs and the id key path, then materializes one HStack row per element, using the indexed identifiers to decide which rows to insert, move, or remove.

Try it — Add a duplicate entry to fruits (for example a second "Apple") and notice the list still renders distinct rows—because identity comes from \.offset, not the string value.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

IndexedIdentifierCollection.swift
struct IndexedIdentifierCollectionDemo: View {
    let fruits = ["Apple", "Banana", "Cherry"]
    var body: some View {
        List(Array(fruits.enumerated()), id: \.offset) { index, fruit in
            HStack {
                Text("\(index + 1).")
                    .foregroundStyle(.secondary)
                Text(fruit)
            }
        }
        .padding()
    }
}
Live preview
{index + 1}. fruit
{index + 1}. fruit
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →