TechnologiesSwiftUI

EditMode enum

iOSmacOStvOSwatchOSvisionOS✓ renders

A mode that indicates whether the user can edit a view's content.

How it works

EditMode is an enumeration that represents whether a view hierarchy is currently being edited, with cases inactive and transient for normal display and active for the editing state. SwiftUI propagates it down the view tree through the environment, where container views like List read it to decide whether to show delete badges, reordering grips, and selection controls. Reach for EditMode when you want a view's editing affordances to turn on and off together, and when you need your own controls to respond to that same state rather than tracking edit status by hand.

  1. Read the editing state from the environment

    EditMode lives in the environment under the editMode key, so any view can observe it with @Environment(\.editMode). A List consults this value automatically: when it becomes active, the rows in the ForEach over fruits reveal their editing controls; when it returns to inactive, they hide again.

  2. Toggle the mode with EditButton

    EditButton is the built-in control that flips the environment's EditMode between active and inactive for you. Placing it in the .toolbar gives the List a standard Edit/Done button without any state of your own, since the button writes directly into the same editMode binding the List reads.

  3. Enable row removal in the active state

    Attaching .onDelete to the ForEach registers a deletion handler that the List only surfaces while EditMode is active. Here the closure calls fruits.remove(atOffsets:), so the delete controls that appear in edit mode actually mutate the backing data.

  4. Enable reordering in the active state

    Similarly, .onMove supplies a reorder handler that becomes reachable through the drag grips shown when EditMode is active. The closure forwards to fruits.move(fromOffsets:toOffset:), letting the user rearrange rows while editing.

  5. Drive your own controls from the same mode

    Because EditMode is a plain Equatable enum carried in the environment, you can branch on it yourself, for example checking editMode?.wrappedValue == .active to show extra UI alongside the List. This keeps custom affordances in sync with the same state that EditButton toggles and the rows respond to.

Try it — Add @Environment(\.editMode) private var editMode to EditModeDemo and place a Text(editMode?.wrappedValue == .active ? "Editing" : "Viewing") above the List to watch the value flip as you tap the Edit button.

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.

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