ios - View Controller 的键命令在模态显示时包含在内

标签 ios uiresponder uikeycommand

我正在努力为我的应用程序添加键盘快捷键。有一个显示另一个 Controller 的 View Controller :

class ViewController: UIViewController {

    override var canBecomeFirstResponder: Bool { true }

    override func viewDidLoad() {
        super.viewDidLoad()

        addKeyCommand(UIKeyCommand(
            input: "M",
            modifierFlags: .command,
            action: #selector(ViewController.handleKeyCommand),
            discoverabilityTitle: "Command from the container view"
        ))
    }

    @objc func handleKeyCommand() {
        present(ModalViewController(), animated: true)
    }

    override func canPerformAction(
        _ action: Selector, withSender sender: Any?
    ) -> Bool {
        if action == #selector(ViewController.handleKeyCommand) {
            return isFirstResponder
        }

        return super.canPerformAction(action, withSender: sender)
    }
}

class ModalViewController: UIViewController {

    override var canBecomeFirstResponder: Bool { true }

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .white
        addKeyCommand(UIKeyCommand(
            input: "D",
            modifierFlags: .command,
            action: #selector(ModalViewController.handleKeyCommand),
            discoverabilityTitle: "Command from the modal view"
        ))

        if !becomeFirstResponder() {
            print("⚠️ modal did not become first responder")
        }
    }

    @objc func handleKeyCommand() {
        dismiss(animated: true)
    }
}

两者都定义了快捷方式。呈现模态视图 Controller 时,可发现性弹出窗口包括用于呈现和呈现 View Controller 的快捷方式。直觉上,只应包含模态视图 Controller 快捷方式(我们不应该能够与呈现 View Controller 交互,对吧?)

我可以通过覆盖呈现 View Controller 的 keyCommands 属性来解决这个问题,但这是个好主意吗?

一般来说,这种行为背后的原因是什么?这是错误还是功能?


更新:将 canPerformAction(_:sender:) 添加到呈现 View Controller (如 @buzzert 所建议),但是问题仍然存在。

最佳答案

这是因为呈现 View Controller (ViewController) 是您的 ModalViewController 响应链中的 nextResponder

这是因为操作系统需要某种方式来从当前显示在屏幕上的 View Controller 一直追溯到应用程序。

如果您的呈现 View Controller 只有当它是第一响应者时才有意义的命令,解决这个问题的最简单方法是简单地覆盖 ViewController 上的 canPerformAction(_:) >,如果不是第一响应者则返回false

例如,

    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if self.isFirstResponder {
            return super.canPerformAction(action, withSender: sender)
        } else {
            return false
        }
    }

否则,如果你想更多地控制响应链中的 nextResponder,你也可以覆盖 nextResponder getter 以“跳过”你的呈现 View Controller 。虽然不推荐这样做,但可以作为其工作原理的说明。

关于ios - View Controller 的键命令在模态显示时包含在内,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61664793/

相关文章:

iOS Swift keyCommands 仅读取数字

ios - iOS模拟器中的命令键

ios - 在 Swift 中监听硬件键盘按键

ios - 如何初始化一个CKAsset?

swift - 在 SwiftUI 中处理 UITextView 的 UIResponder

ios - 查看手势处理 : Detecting gestures on a big view which is a subview of a small view

ios - 我无法在 Swift iOS 中创建 UIResponder nextResponder

ios - iOS AVPlayer 无法播放透明视频,怎么办?

ios - MKMapView是否支持离线 map ,或者离线 map 下载?

ios - 如何实现 JSON 的离线缓存?