Here is my solution as in my case:
STEP 1. Subclass NSViewController and override -performKeyEquivalent(with:)
method:
extension MyViewController {
override func performKeyEquivalent(with event: NSEvent) -> Bool {
switch event.modifierFlags.intersection(NSEvent.ModifierFlags.deviceIndependentFlagsMask) {
case [.command] where event.characters == "\r":
// do something, and....
// return a flag that we have handled this key-stroke combination
return true
default:
// otherwise unhandled (by return `false`)
return false
}
}
}
STEP 2. Setup your controller to observe local events:
class MyViewController: NSViewController {
// ...
// properties and methods...
// ...
override func viewDidLoad() {
super.viewDidLoad()
_ = NSEvent.addLocalMonitorForEvents(matching: .keyDown) { (event) -> NSEvent? in
// process the event and get the handled/unhandled flag;
let isHandled = self.performKeyEquivalent(with: event)
// stop dispatching this event if handled, or...
// dispatch it forward to next receiver if unhandled
return isHandled ? nil : event
}
}
// ...
}
What I found is that the error beep is triggered by one of subsequent calls after you dispatched the event in the block. So, to mute the beep, just stop dispatching it by return nil.
Documentation for reference:
Use +addLocal to install an event monitor that receives events before they are dispatched by -[NSApplication sendEvent:]. In this case, your block should either return a valid NSEvent (which may be the same as the incoming NSEvent, or may be a newly created NSEvent) to cause the event to be dispatched, or it may return nil to stop dispatching of the event. Note that your handler will not be called for events that are consumed by nested event-tracking loops such as control tracking, menu tracking, or window dragging; only events that are dispatched through -[NSApplication sendEvent:] will be passed to your handler.
[self becomeFirstResponder]
in the initialization code of your NSView ? – Universe