SwiftUI: Conditional Context Menu Shown Unexpectedly

446 Views Asked by At

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()
        }
    }
}
1

There are 1 best solutions below

1
Asperi On BEST ANSWER

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 !!