Сочетания клавиш с UIKeyCommand в бета-версии iPadOS 15

По какой-то причине я не могу заставить аппаратные сочетания клавиш работать в iPadOS 15 (бета 5). Они работают для большинства клавиш, но не для клавиш со стрелками и клавиши табуляции.

Кажется, что тот же код хорошо работает при компиляции в Xcode 13 (бета 4) и запуске на симуляторе iPadOS 14.5, но затем отказывается работать при сборке с тем же Xcode, но на iPadOS 15 sim. Я пробовал это на реальных устройствах с бета-версиями iPadOS от 15 до 5 с такими же результатами.

Вот минимальный пример:

      class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        addKeyCommand(UIKeyCommand(title: "UP", action: #selector(handle(key:)), input: UIKeyCommand.inputUpArrow, modifierFlags: []))
        addKeyCommand(UIKeyCommand(title: "DOWN", action: #selector(handle(key:)), input: UIKeyCommand.inputDownArrow, modifierFlags: []))
        addKeyCommand(UIKeyCommand(title: "TAB", action: #selector(handle(key:)), input: "\t", modifierFlags: []))
    }

    @objc func handle(key: UIKeyCommand?) {
        NSLog("Intercepted key: \(key?.title ?? "Unknown")")
    }
}

Я не нашел никаких связанных отчетов или открытых радаров, поэтому подозреваю, что могу что-то здесь упустить. Если об этом нужно сообщить, где я могу сообщить о подобной ошибке?

Спасибо.

2 ответа

Решение действительно состоит в том, чтобы использовать . Однако, поскольку вы используете подкласс вместо добавления ключевых команд для известных клавиш вы можете рассмотреть возможность использования встроенного метода. Это более эффективно, чем добавление каждого по отдельности, и просто более чисто с точки зрения шаблона.

      class ViewController: UIViewController {

    /// - SeeAlso: UIViewController.viewDidLoad()
    override func viewDidLoad() {
        super.viewDidLoad()
        // do other things, nothing connected with UIKeyCommand
    }

    /// - SeeAlso: UIResponder.keyCommands
    override var keyCommands: [UIKeyCommand]? {
        let commands = [
            UIKeyCommand(input: UIKeyCommand.inputUpArrow, modifierFlags: [], action: #selector(actionUp)),
            UIKeyCommand(input: UIKeyCommand.inputDownArrow, modifierFlags: [], action: #selector(actionDown)),
            UIKeyCommand(input: UIKeyCommand.inputLeftArrow, modifierFlags: [], action: #selector(actionLeft)),
            UIKeyCommand(input: UIKeyCommand.inputRightArrow, modifierFlags: [], action: #selector(actionRight))
        ]
        // if your target is iOS 15+ only, you can remove `if` and always apply this rule
        if #available(iOS 15, *) { 
            commands.forEach { $0.wantsPriorityOverSystemBehavior = true }
        }
        return commands
    }
}

private extension ViewController {
   
    @objc func actionUp() { print("up") }
    @objc func actionDown() { print("down") }
    @objc func actionLeft() { print("left") }
    @objc func actionRight() { print("right") }
}

Извините, это ответ, но комментарии не позволяют сделать хороший синтаксис кода :-) Надеюсь, вы не возражаете против моего дополнения, но, возможно, кто-то не знает о и найти его полезным в этом контексте. По крайней мере, я представил пример использования этой новой части API, о которой уже писал создатель @AlexStaravoitau.


Apple утверждает, что:

До iOS 15 система сначала доставляла события клавиатуры в ваши ключевые объекты команд, а затем в системы ввода текста или фокуса. Если ваше приложение ссылается на iOS 14 SDK или более раннюю версию, ваше приложение сохраняет это поведение даже при работе на iOS 15 или более поздней версии.

и это довольно важная маленькая деталь, о которой стоит помнить. Я неправильно прочитал это и подумал, что если вы поддерживаете iOS 14 или ниже, он будет работать по-старому. Но это было мое неправильное понимание, и речь идет о компоновке вообще (например, если вы строите с помощью Xcode 12 или старше и не добавляете дополнительную iOS в библиотеку). Итак, хотя мое приложение по-прежнему поддерживает iOS 12+, ключевые команды больше не работают на новых сборках из Xcode 13 на iOS 15. Оно начало работать только после того, как я адаптировал упомянутый флаг.

Судя по всему, есть новый UIKeyCommand свойство wantsPriorityOverSystemBehavior, который необходимо установить на trueдля некоторых ключей - например, тех, которые я упомянул в своем вопросе: https://developer.apple.com/documentation/uikit/uikeycommand/3780513-wantspriorityoversystembehavior

Другие вопросы по тегам