SwiftUI EditButton on List stopped working in iOS 15
Asked Answered
I

0

8

I used a SwiftUI EditButton() together with a List(), however it suddenly stopped working with iOS15. I do not use a wrapping NavigationView though, however, it worked nicely before. Using a NavigationView is anyways not an option for me.

struct Test: View {
    @State private var items: [String] = ["Item1", "Item2", "Item3"] // mock / demo
    
    var body: some View {
        VTile(padding: 0) {
            HStack {
                Text("Title")
                Spacer()
            }
            .overlay(EditButton())
            
            List {
                ForEach(items, id: \.self) { item in
                    HStack {
                        Text(item)
                        Spacer()
                    }
                }
                .onDelete(perform: delete)
                .onMove(perform: move)
            }
            .listStyle(PlainListStyle())
        }
    }
    
    func move(from source: IndexSet, to destination: Int) {
        // ...
    }
    
    func delete(at offsets: IndexSet) {
        // ...
    }
}

I also tried using @Environment(\.editMode) var editMode but that doesn't work either. The List just mever shows the "move" bars on the right, regardless of the environmental edit-mode.

EDIT: What I just noticed is that after a refresh (close & re-open the view containing the list) the list then is in edit mode. Is thhis a bug or is there a clean implementation approach that does work (without using a NavigationView thought).

Workaround: I therefore came up with the following workaround that solved the issue for now but might have side-effects in some situations. Since as observed, refreshing the list brings it into edit mode. Therefore manually forcing a re-rendering when editmode is toggled (e.g. by observing the editMode environmental variable) brings the desired result. To re-render any SwiftUI element simply apply it an unique id. Changing that id later will force the view to re-render.

@Environment(\.editMode) var editMode
@State private var updateId: UUID = UUID()
// ...
List { /* ... */ }.id(updateId)
// ...
func toggleEditMode() {
    // toggle edit mode
    editMode.toggle()

    // force update
    updateId = UUID()   // <------- update the list
}
Ike answered 23/10, 2021 at 9:35 Comment(4)
What I just noticed, the edit-mode automatically toggles back to inactive when: 1. swiping left on one of the list items such that the red delete button appears (but without deleting it), then 2. tap somewhere to make the delete button disapper againIke
your code seems to work for me, using macos 12.01 with xcode 13.1(RC), targets ios 15 and macCatalyst. Tried on mac 12.01 and iPhone ios15. Although I changed VTile(padding: 0) to VStack(spacing: 10).Maroney
interesting, I'm on xcode 13.0, I'll update now and see if that changes anything. I also got it working now by forcing th elist to refresh (assigning an id and changing the id whenever editMode changes) but it's a dirty workaround.Ike
I'm using NavigationView, but my app has same problem.Lammergeier

© 2022 - 2024 — McMap. All rights reserved.