Brickers
Brickers

Reputation: 192

Indicate that keyUp event has been handled in Swift?

In an NSTextView I am trying to make tab and shift-tab play a role in editing text, without tabs being inserted in the text. Currently I am detecting keypresses via NSTextViewDelegate's keyUp method:

override func keyUp(with event: NSEvent) {
    if let currChar = event.characters {
        if event.keyCode == 48 { // detect tab key
            if event.modifierFlags.rawValue == 256 { // detect no modifier key
                // do something
            } else if event.modifierFlags.rawValue == 131330 { // detect shift modifier
                // do another thing
            }
        }
   }

I can't see anything in the documentation how to indicate to the NSTextView that I want it to ignore the tab key (I have tried the answer shown here, but tabs do not appear to trigger this event), or to prevent the event from moving up the responder chain.

I have also tried calling interpretKeyEvents([event]) at the beginning of my keyUp method, and overriding insertTab and insertBacktab. These are successfully called with the right keypresses, but a tab is still inserted into the text. The documentation seems to suggest it should prevent the tab being inserted:

It [keyDown] can pass the event to Cocoa’s text input management system by invoking the NSResponder method interpretKeyEvents:. The input management system checks the pressed key against entries in all relevant key-binding dictionaries and, if there is a match, sends a doCommandBySelector: message back to the view. Otherwise, it sends an insertText: message back to the view, and the view implements this method to extract and display the text. (emphasis mine)

The documentation talks about an event continuing up the responder chain if it has not been handled - how is this indicated? Is it important that I am using keyUp, not keyDown?

Upvotes: 0

Views: 837

Answers (2)

Marek H
Marek H

Reputation: 5566

Use custom subclass. If these methods are not being called it means the first responder is someone else and has eaten your event. As long as your textview is first responder your keyDown method will be called.

class MyTextView: NSTextView {

    override func insertTab(_ sender: Any?) {
        self.insertText("HELLO", replacementRange: NSMakeRange(0, 0))
        //OR ANY CUSTOM TEXT EDITING, ACTION TO CHANGE FIRST RESPONDER...
    }
    override func insertBacktab(_ sender: Any?) {
        self.insertText("AAAAA", replacementRange: NSMakeRange(0, 0))
        //OR ANY CUSTOM TEXT EDITING, ACTION TO CHANGE FIRST RESPONDER...
    }

}

Educational: "Key Event Handling in Cocoa Applications from WWDC 2010"

Upvotes: 1

rob mayoff
rob mayoff

Reputation: 385500

Yes, it matters that you’re overriding keyUp: instead of keyDown:. The key-down event happens before the key-up event, and NSTextView acts on the key-down event. By the time the system has called your keyUp: override, it’s too late to prevent the default handling of the key-down event.

Upvotes: 1

Related Questions