swift 如何确定多窗口应用程序中不需要的iPadOS外部键盘快捷键的来源?

bvn4nwqk  于 2023-03-28  发布在  Swift
关注(0)|答案(1)|浏览(94)

在撰写本文时,我正在使用Xcode 14.2和iPadOS 16.3.1进行开发。
我正在更新一个现有的应用程序,以支持iPadOS的多个窗口/场景。主场景使用UIKit,子场景主要使用SwiftUI。我将注意力转向测试外部键盘快捷键,这些快捷键已经在应用程序中以前的代码中实现,即:按住外部键盘或运行设备模拟器的计算机键盘上的CMD键。

这些快捷方式选项是从主场景中的视图中实现的,该视图通过以下方式返回值:
override var keyCommands: [UIKeyCommand]?
然而,有时我会看到不需要的/不必要的编辑选项,我没有在项目中显式实现:

有时,打开应用后似乎会出现此不需要的编辑选项。打开子场景后似乎总是存在。即使完全关闭子场景(在UIApplication.shared.openSessions / connectedScenes中不再存在),编辑方面仍会显示。
在其他场景的代码中没有什么明显的东西可以让我把不需要的选项归因于它。有什么想法可以添加跟踪来确定编辑选项的来源吗?
更新:我已经排除了打开子场景作为原因。它也发生在窗口大小从旋转设备。因此,主场景中的某些东西一定是原因。添加测试代码以递归检查所有子视图并没有发现任何奇怪的东西,例如两个视图设置为firstResponder。编辑选项看起来像文本控件可能返回的东西,但我没有。我们还没发现任何可能提供这种信息来源的东西。

6vl6ewon

6vl6ewon1#

我发现UIApplication在调用其canPerformAction(...)方法时对内部**_handleLegacyEmojiKeyboardShortcut:**选择器响应true。我不知道为什么会发生这种情况,但它似乎在窗口调整大小(例如旋转设备)后开始响应true。
我通过以下跟踪代码发现了这一点,该代码针对的是keyCommands被覆盖的视图:

func processResponders(_ action: Selector, withSender sender: Any?, next: UIResponder?) {
    if let next {
        let result = next.canPerformAction(action, withSender: sender)
        print("******** canPerformAction \(next) \(action) \(String(describing: sender)) \(result)")
        processResponders(action, withSender: sender, next: next.next)
    }
}

override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    
    let result = super.canPerformAction(action, withSender: sender)
    print("******** canPerformAction \(action) \(String(describing: sender)) \(result)")
    processResponders(action, withSender: sender, next: next)
    return result
}

我选择的解决方案是定义一个custom UIApplication,并使用以下命令来阻止应用程序类返回true:

import UIKit

class CustomApplication: UIApplication {
    
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        guard sender is UIKeyCommand == false else { return false }
        return super.canPerformAction(action, withSender: sender)
    }

}

相关问题