TechnologiesSwiftUILists and Collections

EditActions struct

iOSmacOStvOSwatchOSvisionOSiOS 16.0+✓ renders

A set of edit actions on a collection of data that a view can offer

How it works

EditActions is an option set that declares which mutating operations a collection-backed view permits while it's being edited — principally moving and deleting rows. SwiftUI consults these options to decide whether to offer the move grips and delete controls that appear when a List or ForEach enters edit mode, so you rarely construct an EditActions value by hand. Instead you opt in to each capability by attaching the corresponding action handler, and reach for the type when you want to reason about, or constrain, the set of edits a dynamic collection should support.

  1. Enable row removal with onDelete

    Supplying an onDelete handler signals that the collection supports the delete action, which is what causes SwiftUI to surface the swipe-to-delete and red minus controls. The closure receives an IndexSet of the affected positions, which you forward straight to the model — here fruits.remove(atOffsets: offsets).

  2. Enable reordering with onMove

    Attaching an onMove handler adds the move action to the set, drawing the drag grips on each row in edit mode. The closure hands you a source IndexSet and a destination index, applied to the array with fruits.move(fromOffsets: src, toOffset: dst).

  3. Bind the actions to a dynamic ForEach

    Edit actions belong on a ForEach driven by mutable data, since SwiftUI needs identity to map offsets back to elements. The ForEach(fruits, id: \.self) here over the @State array fruits is what the move and delete handlers reorder and remove from.

  4. Toggle edit mode with EditButton

    The enabled actions only become visible once the surrounding view enters edit mode. Placing an EditButton() in the .toolbar flips the environment's edit mode on and off, revealing the move grips and delete affordances that onDelete and onMove opted into.

Try it — Delete the .onMove { src, dst in ... } modifier and tap Edit — the drag-to-reorder grips disappear while the delete controls remain, showing that each handler contributes its own action to the set independently.

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.

EditActions.swift
struct EditActionsDemo: View {
    @State private var fruits = ["Apple", "Banana", "Cherry", "Date"]
    var body: some View {
        NavigationStack {
            List {
                ForEach(fruits, id: \.self) { fruit in
                    Text(fruit)
                }
                .onDelete { offsets in
                    fruits.remove(atOffsets: offsets)
                }
                .onMove { src, dst in
                    fruits.move(fromOffsets: src, toOffset: dst)
                }
            }
            .navigationTitle("Fruits")
            .toolbar { EditButton() }
        }
    }
}
Live preview
fruit fruit fruit fruit 9:41 Fruits
fruit fruit fruit fruit 9:41 Fruits
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →