Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable the Delete key shortcut in the Edit menu of a SwiftUI App on macOS?

Tags:

swiftui

If I add the .onDeleteCommand to a List, the Edit -> Delete menu item is enabled when a row is selected. However, the delete key doesn't work. I see that the menu item doesn't have the shortcut listed. When trying to replace it using a CommandGroup, the shortcut becomes command + delete

How do I get the Edit -> Delete MenuItem to use the delete key shortcut? Or how do I enable using the delete key to delete rows in a List on the macOS?

Delete Menu Item


@main
struct MyApp: App {
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        // Turns it into command+delete
//        .commands {
//            CommandGroup(replacing: CommandGroupPlacement.pasteboard) {
//                Button("Delete", action: {
//                    print("Custom Delete")
//                })
//                .keyboardShortcut(.delete)
//            }
//        }
    }
}

struct ContentView: View {
    @State var data = Data()
    @State var selection = Set<Int>()
    
    var body: some View {
        List.init(data.models, id: \.id, selection: $selection) {
            Text("Name: \($0.name)")
                
        }
        .keyboardShortcut(.delete)  // This does not work
        .onDeleteCommand(perform: { // This works when clicking in the menu
            print("Delete row")
        })
    }
}

struct Model: Identifiable {
    let id: Int
    let name: String
}

struct Data {
    var models = [Model(id: 1, name: "First")]
}
like image 649
joels Avatar asked Nov 19 '20 16:11

joels


1 Answers

While reproducing your problem I misinterpreted delete to be forwardDelete and therefore pressed the wrong key while testing. (Coming from a full-size keyboard where keys are labeled backspace and delete can be confusing.)

But I got your custom delete command to work as you would expect it. Just make sure you pass in an empty array for the modifiers argument:

.commands {
    CommandGroup(replacing: CommandGroupPlacement.pasteboard) {
        Button("Delete", action: {
            print("Custom Delete")
        })
        .keyboardShortcut(.delete, modifiers: [])
    }
}

If you don't like the idea of having a "global command" to do it. Just add the delete button to the toolbar with the same keyboard shortcut, calling the same delete method as the onDeleteCommand:

List.init(data.models, id: \.id, selection: $selection) {
    Text("Name: \($0.name)")
}
.keyboardShortcut(.delete, modifiers: [])
.onDeleteCommand(perform: delete)
.toolbar(content: {
    Button(action: delete){
        Image(systemName: "trash.fill")
    }
    .keyboardShortcut(.delete, modifiers: [])
    .disabled(selection.isEmpty)
})
like image 169
pd95 Avatar answered Oct 08 '22 03:10

pd95