Swift – Detecting key press event in Swift

macosswift

I'm trying to find a way to detect if a key (on a keyboard) has been pressed on Swift. Any ideas and suggestions will be greatly appreciated.

Best Solution

Since you updated your question and you wanted to know how to do this for a window, here's an answer. Subclass NSWindow and use this subclass instead.

Your custom class should look like this:

import Cocoa

class EditorWindow: NSWindow {
    override func keyDown(event: NSEvent) {
        super.keyDown(event)
        Swift.print("Caught a key down: \(event.keyCode)!")
    }
}

If you've made your window in Interface Builder/XCode, click the window object and go to the Attribute Inspector (++3). The Attribute Inspector will be in the sidebar on the right. Making sure your window is selected in Interface Builder, at the top of the Attribute Inspector in the Custom Class area put your new class in the class input.

Attribute Selector

In order to communicate the event from the this window class to my app I add a function to the window that accepts a callback function that I then store in an array of callback functions. I get access to this window through the AppDelegate which can get a weak reference to the current main window. Then in the above function I iterate overall the callbacks and call it with the NSEvent as the argument. I also first check to see if any command keys like the option keys are being pressed first through modifierFlags property on the event. It ends up looking like this:

import Cocoa

typealias Callback = (NSEvent) -> ()

class KeyCaptureWindow: NSWindow {

    var keyEventListeners = Array<Callback>()

    override func keyDown(event: NSEvent) {
        if event.modifierFlags.contains(NSEventModifierFlags.CommandKeyMask) {
            super.keyDown(event)
            return
        }
        for callback in keyEventListeners {
            callback(event)
        }
    }

    func addKeyEventCallback(callback: Callback) {
        keyEventListeners.append(callback)
    }


}

And then elsewhere in my code I have a line like so:

    let appDelegate = NSApplication.sharedApplication().delegate as! AppDelegate
    let mainWindow = appDelegate.getWindow()
    mainWindow.addKeyEventCallback(handleKeyEvent)

I added the getWindow method to my app delegate class. This method returns the NSWindow cast to KeyCaptureWindow. There may be a better way to do all this but this works for me. Another way to possibly do this is to use first responders and NSView, but that's not how I've been doing it.