SwiftUI EditButton in HStack not activating edit mode

Viewed 1411

As part of a bigger Form I'd like to have a Section with a List whose entries can be reordered.

In the whole view it should be only possible to edit that particular list, nothing else. Therefore I'd like to have the EditButton near the List.

If I just set the EditButton as the Section header, reordering List items works but I can't display a section title:

struct ContentView: View {
    
    private let items = Range(1...4).map { "Item " + String($0) }
    
    var body: some View {
        Form {
            Section(header: EditButton()) {
                ForEach(items, id: \.self) { item in
                    Text(item)
                }
                .onMove(perform: reorderItems)
                .onDelete(perform: deleteItems)
            }
        }
    }

    func reorderItems(from sourceIndices: IndexSet, to destinationIndex: Int) { /* ... */ }

    func deleteItems(at offsets: IndexSet) { /* ... */ }
}

enter image description here

But if I wrap the EditButton in a HStack to display the button on the right, a tap on "Edit" changes the button's title to "Done" but doesn't start List's edit mode anymore:

struct ContentView: View {

    @Environment(\.editMode) var editMode
    
    private let items = Range(1...4).map { "Item " + String($0) }
    
    var body: some View {
        Form {
            Section(header: HStack {
                Text("Section title")
                
                Spacer()
                
                EditButton()
            }.environment(\.editMode, self.editMode)) {
                ForEach(items, id: \.self) { item in
                    Text(item)
                }
                .onMove(perform: reorderItems)
                .onDelete(perform: deleteItems)
            }
        }
    }

    func reorderItems(from sourceIndices: IndexSet, to destinationIndex: Int) { /* ... */ }

    func deleteItems(at offsets: IndexSet) { /* ... */ }
}

enter image description here

I also tried, as the code shows, passing the editMode environment variable to the HStack, but nothing helped.

Is there any way to get the EditButton inside an HStack working?

(Remark: As the List is part of a bigger Form, placing the EditButton out of the Section as suggested here is not an option in my case.)

1 Answers

Here is working solution - looks like they require that EditButton was a root view of section, so we can construct everything else above it. (tested with Xcode 11.4 / iOS 13.4)

Note: @Environment(\.editMode) var editMode is not needed

demo

Section(header:
    EditButton().frame(maxWidth: .infinity, alignment: .trailing)
        .overlay(Text("Header"), alignment: .leading)
)
{
    ForEach(items, id: \.self) { item in
        Text(item)
    }
    .onMove(perform: reorderItems)
    .onDelete(perform: deleteItems)
}
Related