swiftui · note · identity
List Row State Reset Fixes
Context
List rows that reset after a filter, sort, or insert usually have an identity problem, not a rendering problem. Once you know that, the fix gets much easier.
The snippet
ForEach(items.indices, id: \.self) { index in
RowView(item: items[index])
}
Why this works
This code is only safe for static data. The moment rows move, insert, or delete, index identity stops matching the logical item and SwiftUI starts reusing the wrong row state.
Use this checklist:
- does each item have a stable ID?
- is the ID created with the data, not the view?
- are you sorting or filtering the collection after the ID is assigned?
- do row-specific controls keep their state when the list changes?
- does the bug disappear if you replace index identity with model identity?
If the answer to that last question is yes, you found the real problem.
Use it when…
- toggles jump to the wrong row
- expansion state disappears after a refresh
- list animations look like full row replacement
Avoid it when…
- the collection is truly static
- the identity is already stable and the bug is elsewhere
- the list is not the actual source of the state reset
Takeaway: Fix the identity model first, then look at state.