Ora

How do I enable Edit mode in SwiftUI?

Published in SwiftUI Edit Mode 4 mins read

To enable Edit mode in SwiftUI, you primarily use the built-in EditButton component, especially when working with list views that support item deletion or reordering. Tapping this button allows users to intuitively toggle editing mode on or off for items within the list.

Understanding Edit Mode in SwiftUI

Edit mode in SwiftUI provides a standardized way for users to interact with collections of data, typically for reordering, deleting, or selecting items. When edit mode is active, SwiftUI views can change their appearance or behavior to facilitate these actions.

1. Using the EditButton for Automatic Control

The most straightforward way to enable and manage Edit mode, particularly within a List or ForEach view that supports deletion or reordering, is by adding an EditButton.

How it works:

  • The EditButton is a standard system button that automatically changes its title between "Edit" and "Done" (or localized equivalents) as it's tapped.
  • When placed within a navigation bar's toolbar or any view hierarchy, it automatically detects the presence of a List or other editable content in its environment and toggles their editing state.
  • For a List configured to support deletion (.onDelete) or reordering (.onMove), the EditButton will reveal the respective controls (e.g., delete circles, reorder handles) when tapped.

Example:

import SwiftUI

struct MyEditableListView: View {
    @State private var items = ["Apple", "Banana", "Cherry", "Date"]

    var body: some View {
        NavigationView {
            List {
                ForEach(items, id: \.self) { item in
                    Text(item)
                }
                .onDelete(perform: deleteItem) // Enable deletion
                .onMove(perform: moveItem)     // Enable reordering
            }
            .navigationTitle("Fruits")
            .toolbar {
                EditButton() // Place the EditButton in the toolbar
            }
        }
    }

    func deleteItem(at offsets: IndexSet) {
        items.remove(atOffsets: offsets)
    }

    func moveItem(from source: IndexSet, to destination: Int) {
        items.move(fromOffsets: source, toOffset: destination)
    }
}

In this example, the EditButton() placed in the toolbar will allow users to tap it, revealing the delete and reorder controls for the items in the List. Tapping "Done" will hide these controls.

2. Programmatic Control with @Environment(\.editMode)

While EditButton handles the user interface and state toggling automatically, SwiftUI's Edit mode is ultimately managed through an environment value: @Environment(\.editMode). You can observe or directly control this value for more custom scenarios or if you prefer a different UI trigger.

  • The @Environment(\.editMode) property wrapper provides a binding to the current EditMode state (e.g., .inactive, .active, .transient).
  • You can use this to create custom "Edit" buttons or to make parts of your UI react to the current edit mode.

Example:

import SwiftUI

struct CustomEditableView: View {
    @State private var items = ["Task 1", "Task 2", "Task 3"]
    @Environment(\.editMode) private var editMode // Observe editMode

    var body: some View {
        NavigationView {
            VStack {
                // Custom UI that responds to editMode
                if editMode?.wrappedValue == .active {
                    Text("Editing is active!")
                        .foregroundColor(.red)
                } else {
                    Text("Not in edit mode.")
                        .foregroundColor(.green)
                }

                List {
                    ForEach(items, id: \.self) { item in
                        Text(item)
                    }
                    .onDelete(perform: deleteItem)
                    .onMove(perform: moveItem)
                }
            }
            .navigationTitle("Tasks")
            .toolbar {
                // You can still use EditButton, or...
                // ... a custom button that toggles editMode manually:
                Button(editMode?.wrappedValue == .active ? "Done" : "Custom Edit") {
                    editMode?.wrappedValue = (editMode?.wrappedValue == .active ? .inactive : .active)
                }
            }
        }
    }

    func deleteItem(at offsets: IndexSet) {
        items.remove(atOffsets: offsets)
    }

    func moveItem(from source: IndexSet, to destination: Int) {
        items.move(fromOffsets: source, toOffset: destination)
    }
}

In this example, we observe the editMode environment value to display a message. The custom button in the toolbar manually toggles the editMode state, which in turn activates the delete and reorder functionality for the List.

Summary of Edit Mode Options

Method Description Primary Use Case Flexibility
EditButton() A built-in SwiftUI button that automatically toggles the editMode environment value and updates its title ("Edit" / "Done"). Standard list editing, quick implementation. Low (fixed UI and behavior).
@Environment(\.editMode) Accesses the current EditMode state from the environment. Can be observed to make UI reactive or modified to programmatically control edit mode. Custom editing interfaces, conditional UI changes. High (allows custom triggers and responses).

By utilizing either the convenient EditButton or the more flexible @Environment(\.editMode), you can effectively enable and manage edit mode in your SwiftUI applications.