4

出于某种原因,我无法在 iPadOS 15(beta 5)中使用硬件键盘快捷键。它们适用于大多数键,但不适用于箭头键和 Tab 键。

在 Xcode 13(beta 4)中编译并在 iPadOS 14.5 模拟器上运行时,相同的代码似乎运行良好,但在使用相同的 Xcode 但在 iPadOS 15 sim 上构建时拒绝运行。我已经在 iPadOS 15 beta 到 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")")
    }
}

我没有找到任何相关的报告或打开的雷达,所以我怀疑我可能在这里遗漏了一些东西。如果应该报告,我在哪里报告这样的错误?

谢谢你。

4

2 回答 2

5

显然,有一个新UIKeyCommand属性wantsPriorityOverSystemBehavior,需要true某些键设置 - 就像我在问题中提到的那样:https ://developer.apple.com/documentation/uikit/uikeycommand/3780513-wantspriorityoversystembehavior

于 2021-08-11T22:45:06.833 回答
1

解决方案确实是使用wantsPriorityOverSystemBehavior. 但是,由于您使用的是子类UIResponder而不是为已知键添加键命令,因此您可以考虑使用内置方法。它比单独添加每个更有效,并且在模式方面更干净。

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

很抱歉,这是一个答案,但评论不允许使用漂亮的代码语法 :-) 希望您不介意我的补充,但也许有人不知道keyCommands并发现它在这种情况下很有用。至少我提供了一个示例,说明如何使用创建者 @AlexStaravoitau 已经写过的 API 的这个新部分。


苹果声称:

在 iOS 15 之前,系统首先将键盘事件传递给您的键盘命令对象,然后再传递给文本输入或焦点系统。如果您的应用链接到 iOS 14 SDK 或更早版本,您的应用会保留该行为,即使在 iOS 15 或更高版本上运行时也是如此。

这是一个非常重要的小细节,值得牢记。我误读了它,并认为如果您支持 iOS 14 或更低版本,它将以旧方式工作。但这是我的错误理解,它根本与链接有关(例如,如果您使用 Xcode 12 或更早版本构建并且不在库中添加额外的 iOS)。因此,即使我的应用程序仍然支持 iOS 12+,关键命令不再适用于 iOS 15 上的 Xcode 13 的新版本。它只有在我调整了提到的标志后才开始工作。

于 2021-12-03T18:57:18.743 回答