swiftuieditmode

SwiftUI: Conditional Context Menu Shown Unexpectedly


In the following SwiftUI view, why does the conditional .contextMenu not work correctly?

Steps:

  1. Long press the list item
  2. Tap Edit
  3. Long press the list item again

On the second long press the context menu should not appear because editMode?.wrappedValue is .active. But it does appear. How to fix that?

struct ContentView: View {
    @Environment(\.editMode) private var editMode
    
    var body: some View {
        let contextMenu = ContextMenu {
            Button("Do nothing", action: {})
        }
        VStack(alignment: .leading, spacing: 12) {
            EditButton().padding()
            List {
                ForEach(1..<2) {i in
                    Text("Long press me. Editing: \((editMode?.wrappedValue == .active).description)")
                        .contextMenu(editMode?.wrappedValue == .active ? nil : contextMenu)
                }
                    .onDelete(perform: { _ in })
                    .onMove(perform: { _, _ in })
            }
            Spacer()
        }
    }
}

Solution

  • Works fine with Xcode 14 / iOS 16

    Here is possible workaround for older versions (it is possible to try different places for .id modifier to have appropriate, acceptable, UI feedback)

    Tested with Xcode 13.4 / iOS 15.5

    Text("Long press me. Editing: \((editMode?.wrappedValue == .active).description)")
        .contextMenu(editMode?.wrappedValue == .active ? nil : contextMenu)
        .id(editMode?.wrappedValue)    // << this !!