Oh, would you look at that? It's nothing at all to do with my variables. It's SwiftUI and these damned Environment variables.
This time it was @Environment(\.dismiss) on the view that contains the List, not the rows inside the List.
This is what is supposed to happen:
The user taps a button in MainView.
ItemsListView opens, which contains the List.
The user does something in ListItemsView, such as deleting an Item.
In order to close ItemsListView the user taps a button in that view, which merely calls dismiss(). dismiss() was used to avoid using a @State var in MainView and a corresponding @Binding var in ItemsListView.
This should work, right?
Wrong.
What actually happens is this:
The user taps a button in MainView.
ItemsListView opens, which contains the List.
The user swipes an ItemRow, then taps the delete button.
The confirmation dialog appears, and is attached to the specific row.
_dismiss is changed - for some reason - in ItemsListView, which causes the view to redraw, causing the List to redraw, causing every ItemRow to redraw, causing the confirmation dialog to disappear because the row it was attached to no longer exists.
Obviously, the fix here is to revert to using @State and @Binding vars, and that does indeed work.
So the question becomes: Why on Earth did dismiss change in ItemsListView? Your guess is as good as mine.
7 hours wasted.