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

Posted

技术标签:

【中文标题】如何在 Mac Catalyst 应用程序中禁用默认键盘导航?【英文标题】:How to disable default keyboard navigation in Mac Catalyst app? 【发布时间】:2020-04-10 20:06:55 【问题描述】:

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

我在UITableView 文档中找不到对此功能的任何引用。 Mac Catalyst 的Human Interface Guidelines 提到“自动支持基本的 Mac 功能,例如 ... 键盘导航”,所以我想这是一个有意的功能,但我找不到任何进一步的参考或文档。

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

【问题讨论】:

【参考方案1】:

自 2021 年 11 月 6 日起更新

看起来 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 自动将向上/向下箭头的 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
        )
    

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

【讨论】:

我尝试使用它,因为我的 resignFirstResponder 解决方案在 macOS 11.5 中停止工作。首先,我必须在UITableView 子类中添加canBecomeFirstResponder=true,否则它的keyCommands 将不会被调用。但即使这样做,默认的键盘命令仍在运行。我确认tableView.keyCommands 之前有向上/向下箭头命令,现在为零,所以我不知道默认命令来自哪里。此解决方案是否仍然适合您? @arlomedia 请查看我的更新答案,如果这对您有用,请告诉我。我已经在 macOS 11.6、macOS 12 和 iOS 15 上的示例项目中对其进行了测试。 感谢您的更新!这对我有用,但表中的第一行有时仍会突出显示。我刚刚发布了一个从 Apple DTS 票证中获得的更简单的解决方案。 谢谢@arlomedia!【参考方案2】:

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

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

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

【讨论】:

【参考方案3】:

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

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

这解决了它!现在默认键盘导航一打开就会关闭,并且不会干扰我应用的自定义键盘导航。

(没有延迟就不行了。)

【讨论】:

此解决方案在 macOS 11.5 中停止为我工作。【参考方案4】:

借助 UITableView 和 UICollectionView 的 selectionFollowsFocus 属性,iOS 14 / macOS 11 可以更轻松地禁用此行为:

tableView.selectionFollowsFocus = false

【讨论】:

遗憾的是,这对我没有任何影响。 (我尝试在加载/显示表格之前和之后调用它。)

以上是关于如何在 Mac Catalyst 应用程序中禁用默认键盘导航?的主要内容,如果未能解决你的问题,请参考以下文章

Mac Catalyst 应用程序如何处理生命周期转换?

如何更改 Mac Catalyst 窗口场景中的窗口标题?

如何在 Mac Catalyst 中检测窗口大小调整?

如何修复“读写数据沙箱:使用 Mac Catalyst 时出错”

Mac Catalyst - 保存文件的标准对话框

如何在 Mac Catalyst 13.0+ swift 中打开 Finder