Erik
Erik

Reputation: 2148

How do I listen to key presses in a Mac Catalyst app?

I have a simple iOS game that I am porting to Mac. I would like for the user to be able to control the game using their keyboard. There is not native text input (like UITextField, UITextView).

How do I listen to key down events in a Mac Catalyst app? It does not seem trivial.

UIKeyCommand does not work because it seems to be made for combinations (e.g. cmd+c). I could create a fake text field, but I am looking for a cleaner way to do this. I want to listen to single letters and numbers.

Can I integrate NSResponder::keyDown(with:) somehow?

Upvotes: 5

Views: 2271

Answers (1)

Stefan
Stefan

Reputation: 5461

You can just override the pressesBegan method. Here is the sample code I use in my game to control a player. It uses UIKeyCommand for special command keys like the Arrow keys and key.character to react on a special character. The original code comes from the Apple Catalyst Documentation.

override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {

    var didHandleEvent = false
    for press in presses {
        guard let key = press.key else { continue }
        if key.charactersIgnoringModifiers == UIKeyCommand.inputLeftArrow || key.characters == "a" {
            self.moveLeft(self)
            didHandleEvent = true
        } else if key.charactersIgnoringModifiers == UIKeyCommand.inputRightArrow || key.characters == "d" {
            self.moveRight(self)
            didHandleEvent = true
        } else if key.charactersIgnoringModifiers == UIKeyCommand.inputUpArrow || key.characters == "w" {
            self.moveForward(self)
            didHandleEvent = true
        } else if key.charactersIgnoringModifiers == UIKeyCommand.inputDownArrow || key.characters == "s" {
            self.moveBackward(self)
            didHandleEvent = true
        } else if key.characters == "q" {
            self.turnLeft(self)
            didHandleEvent = true
        } else if key.characters == "e" {
            self.turnRight(self)
            didHandleEvent = true
        }
    }

    if didHandleEvent == false {
        // Didn't handle this key press, so pass the event to the next responder.
        super.pressesBegan(presses, with: event)
    }
}

Upvotes: 8

Related Questions