Как правильно использовать UIResponder.pressesBegan для обнаружения ввода с несколькими клавишами

#ios #swift #keyboard

#iOS #swift #клавиатура

Вопрос:

Я работаю над проектом iOS 13 , который включает представление, которое можно использовать в качестве калькулятора. Числовой блок, используемый для ввода чисел и операторов ( — * / …), создается с помощью simple UIButtons . Текущее значение отображается в a UILabel .

Теперь я хотел бы расширить существующий код, чтобы он также принимал ввод с подключенных аппаратных клавиатур. Я расширил UILabel для обработки UIResponder метода 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)
    }
}
  

Это отлично работает при использовании клавиатуры с цифровым блоком. Тем не менее, я хотел бы также поддерживать клавиатуру без цифрового блока. В этом случае * , например, знак можно ввести только с помощью двух клавиш Shift (на клавиатуре с немецкой раскладкой).

Однако при вводе Shift presses:with: метод вызывается дважды. Один раз для Shift ключа и один раз для ключа. Я не уверен, почему нажатия — это Set когда каждое нажатие клавиши обрабатывается отдельно.

Итак, как определить комбинации нескольких клавиш?

Ответ №1:

Вы можете проверить свойство key.modifierFlags . Тип:

 public struct UIKeyModifierFlags : OptionSet
  

Вам нужен флаг .shift .
Вы можете сравнить флаги modifierFlags с одним значением или литералом массива:

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

ПРИМЕЧАНИЕ # 1:

Вы должны выяснить, какой код ключа (UIKeyboardHIDUsage) сопоставлен с немецкой клавиатурой » «, я нахожу его из какого-то источника.Клавиша closebracket (48 или 0x30). Если неправильно, скажите мне, и я исправлю это. Кроме того, вы можете проверить отправку реальных символов из key.characters (как строковый тип)

Некоторый прототип кода здесь:

 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)
    }
}

  

ПРИМЕЧАНИЕ # 2:

Не нужно различать сдвиг влево и сдвиг вправо для флагов .modifier — они отличаются только в .keyCode