如何在 Mac Catalyst 应用程序中禁用默认键盘导航?

How to disable default keyboard navigation in Mac Catalyst app?

我注意到我可以通过按 Mac 键盘上的向上和向下箭头键在 Mac Catalyst 应用程序的 UITableView 中单步执行行。但是,这会干扰我的一个视图控制器中的现有功能。有没有办法禁用它?

我在 UITableView documentation. The Human Interface Guidelines 中找不到任何关于此功能的参考,因为 Mac Catalyst 提到 "automatic support for fundamental Mac features, such as ... keyboard navigation," 所以我想这是一个有意的功能,但我找不到对其的任何进一步参考或文档。

我还没有在我的应用程序中看到 "automatic" 键盘导航的任何其他示例,但理想情况下 Apple 会发布完整的列表,以便我们知道如何使用或在需要时禁用内置的- 功能。

我进一步注意到,默认箭头键导航仅在单击 table 中的一行后才开始,所以我猜想 table 必须承担第一响应者的角色。我将此添加到我的 table 的委托 class:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    #if TARGET_OS_MACCATALYST
    [tableView performSelector:@selector(resignFirstResponder) withObject:nil afterDelay:0.1];
    #endif
}

修好了!现在默认键盘导航一打开就关闭,不会干扰我的应用程序的自定义键盘导航。

(一拖再拖没成功。)

截至 2021 年 11 月 06 日的更新

看起来 Apple 一直在改变默认焦点系统的工作方式,我以前的解决方案不再有效或不再需要。

UIKeyCommand 有一个新的 wantsPriorityOverSystemBehavior: Bool 属性 需要设置为 true 以便我们的子类接收某些类型的命令,包括箭头键命令。

从至少 Xcode 13.1 和 macOS 11.6 开始,也许更早,我们现在可以简单地将以下内容添加到 UITableViewController 子类中,以用自定义键盘导航处理替换默认的焦点行为:

class TableViewController: UITableViewController {
    override var keyCommands: [UIKeyCommand]? {
        let upArrowCommand = UIKeyCommand(
            input: UIKeyCommand.inputUpArrow,
            modifierFlags: [],
            action: #selector(handleUpArrowKeyPress)
        )
        upArrowCommand.wantsPriorityOverSystemBehavior = true
        
        let downArrowCommand = UIKeyCommand(
            input: UIKeyCommand.inputDownArrow,
            modifierFlags: [],
            action: #selector(handleDownArrowKeyPress)
        )
        downArrowCommand.wantsPriorityOverSystemBehavior = true
        
        return  [
            upArrowCommand,
            downArrowCommand
        ]
    }

    @objc
    func handleUpArrowKeyPress () {
    }

    @objc
    func handleDownArrowKeyPress () {
    }
}

上一个答案(不再有效或需要)

Catalyst 自动将 up/down 箭头的 UIKeyCommands 分配给 UITableView 个实例。 iOS 不会发生这种情况。您可以通过在 UITableViewControllerviewDidLoad() 中设置断点并检查 tableView.keyCommands.

来查看实际效果

所以我创建了一个非常简单的 UITableView 子类并通过返回 nil:

禁用了默认的 keyCommmands
class KeyCommandDisabledTableView: UITableView {
    override var keyCommands: [UIKeyCommand]? {
        return nil
    }
}

然后我更新了我的 UITableViewController 子类以使用新的 KeyCommandDisabledTableView 子类:

class MyTableViewController: UITableViewController {
    override func loadView() {
        self.view = KeyCommandDisabledTableView(
            frame: .zero, 
            style: .plain // or .grouped
        )
    }
}

瞧瞧!默认箭头键处理已消失,现在正在调用我的应用程序的自定义箭头键处理。

iOS 14 / macOS 11 使禁用此行为变得更加容易,这要归功于 UITableView 和 UICollectionView 的 selectionFollowsFocus 属性:

tableView.selectionFollowsFocus = false

这是我从 Apple DTS 收到的另一个解决方案。只需将其添加到 table 视图委托:

func tableView(_ tableView: UITableView, canFocusRowAt indexPath: IndexPath) -> Bool {
    return false
}

这适用于 macOS 11.6 和 12.0。我没有 10.15 或 11.5 Mac 来测试,所以我也会保留我之前的 resignFirstResponder 解决方案。