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.
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 barefruitsarray into index/value pairs, which is exactly the indexed shapeIndexedIdentifierCollectionrepresents.Select the identifier with the id parameter
The
id:argument tells the collection which property uniquely identifies each row. Hereid: \.offsetnames 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.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 whileText(fruit)shows the element itself.Plug the collection into a List
An
IndexedIdentifierCollectionis consumed by identity-aware containers likeListandForEach. TheList(...)initializer takes the indexed pairs and theidkey path, then materializes oneHStackrow per element, using the indexed identifiers to decide which rows to insert, move, or remove.
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.
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()
}
}