How it works
A ReorderDifference captures the result of moving elements within an ordered collection: it records where items started and where they ended up after a reordering operation. SwiftUI produces this difference when a person drags a row to a new position in a list, giving you a structured description of the move rather than a raw before-and-after snapshot. Reach for it when you need to translate an interactive reorder gesture into a concrete mutation of your own data model, so the on-screen order and your stored order stay in agreement.
Receive the move from onMove(perform:)
Reordering begins when a row-presenting view reports that the user dragged content to a new slot. Attaching
.onMoveto theForEachoveritemsregisters a handler that fires once the drag completes, handing you the difference assource(the offsets being moved) anddestination(the target index).Read the source and destination offsets
The reorder difference is expressed as a set of moved offsets and a single insertion point. In the closure,
sourceis anIndexSetdescribing which positions were picked up anddestinationis the index they should land before, so together they fully describe the requested rearrangement without ambiguity.Apply the change to your model
Applying the difference is what keeps your data authoritative. Calling
items.move(fromOffsets: source, toOffset: destination)mutates the backing array to match the gesture; becauseitemsis@State, that mutation re-renders theListwith the rows in their new order.Let people initiate reordering
A reorder difference is only generated when the list is editable and the user can grab rows. Placing an
EditButton()in the.toolbartoggles the list's edit mode, surfacing the drag handles that letonMovecapture the move in the first place.
.onMove closure with print("\(source) -> \(destination)") (omitting the items.move(...) call) and drag a row: the printed offsets show the reorder difference SwiftUI computed, while the rows snap back because nothing applied it to the model.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 ReorderDifferenceDemo: View {
@State private var items = ["Apples", "Bread", "Milk", "Eggs"]
var body: some View {
NavigationView {
List {
ForEach(items, id: \.self) { item in
Text(item)
}
.onMove { source, destination in
items.move(fromOffsets: source, toOffset: destination)
}
}
.navigationTitle("Groceries")
.toolbar { EditButton() }
}
}
}