0

I am working on an iOS 13+ project which includes a view that can be used as calculator. The number block used to input numbers and operators (+ - * / ...) is build using simple UIButtons. The current value is shown in a UILabel.

Now I would like to extend the existing code to also accept input from connected hardware keyboards. I have extended UILabel to handle the UIResponder method pressesBegan:withEvent:

override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
    guard let key = presses.first?.key else { return }

    switch key.keyCode {
    case .keyboard1:
    case .keypad1:
        insertNumber(1)
    case .keyboard2:
    case .keypad2:
        insertNumber(2)

    ...        

    case .keypadPlus:
        add()

    ...

    default:
        super.pressesBegan(presses, with: event)
    }
}

This works fine when using a keyboard with a numberblock. However, I would like to also support keyboard without a numberblock. In this case the * sign for example can only be entered using two keys Shift + (on a Keyboard with German layout).

However, when typing Shift +the presses:with: method is called twice. Once for the Shift key and once for the + key. I am not sure why presses is Set when each keystroke is handled separately.

So, how to detect multi key combinations?

Andrei Herford
  • 17,570
  • 19
  • 91
  • 225

1 Answers1

1

You can check key.modifierFlags property. The type is:

public struct UIKeyModifierFlags : OptionSet

The flag you need is .shift. You can compare modifierFlags to single value or array literal:

if key.modifierFlags == .shift {
 // position of these two flags doesn't matter
}

NOTE#1:

You should find out which keycode(UIKeyboardHIDUsage) mapped to German keyboard "+", I find it from some source to be .keyboardCloseBracket (48, or 0x30). If wrong, tell me and I will correct it. Also, you can check real characters send from key.characters (as String type)

Some prototype code here:

override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
    guard let key = presses.first?.key else { return }
    switch key.keyCode {
    ... (many keyCode cases omitted)
    case .keyboardCloseBracket: // See NOTE#1
        if key.modifierFlags == .shift {
            // yout want "shift + " as "*"
        } else {
            // not the state for plus you want, pass it
            super.pressesBegan(presses, with: event)
        }
    ... 
    default:
        super.pressesBegan(presses, with: event)
    }
}

NOTE#2:

No need to tell between left-shift and right-shift for .modifierFlags -- They are different only in .keyCode

John Chang
  • 11
  • 1
  • 1