全局快捷键不起作用MacOS-HotKey

问题描述

我正在尝试使用HotKey实现快捷键“ Command + Option + J”,由于某种原因,它将无法在视图控制器外部运行。该应用通过菜单栏下拉菜单实现,因此没有实际的窗口显示在最前面。我希望我的消息能打印出来。我有两个按钮,注册和注销,当我注册并打印出键盘时,我看到它已经注册了,所以我认为这是可行的。不幸的是,尽管当我在另一个窗口打开或在桌面视图上按组合键时,没有打印注释。任何帮助将不胜感激。

//
//  ViewController.swift
//

import Cocoa
import AppKit
import HotKey
import Carbon

class ViewController: NSViewController {

    @IBOutlet var pressedLabel: NSTextField!
    
    private var hotKey: HotKey? {
        didSet {
            guard let hotKey = hotKey else {
                pressedLabel.stringValue = "Unregistered"
                return
            }

            pressedLabel.stringValue = "Registered"
            hotKey.keyDownHandler = { [weak self] in
            NSApplication.shared.orderedWindows.forEach({ (window) in
               print("woo")
            })
            }
    }
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        register(self)
        // Do any additional setup after loading the view.
    }
    
    @IBAction func unregister(_ sender: Any?) {
        hotKey = nil
        print("the hot key is ",hotKey?.keyCombo)

        
    }
    

    @IBAction func register(_ sender: Any) {
        hotKey = HotKey(keyCombo: KeyCombo(key: .j,modifiers: [.command,.shift])
        )
    }
    
}

解决方法

这可能是参考问题

private var hotKey: HotKey?

HotKey配置旨在保持有效。它处理了全局按键事件,然后调用了回调。如果将其放入视图控制器中,然后从屏幕上删除视图控制器的窗口或以其他方式取消分配,则其私有HotKey引用也将消失,因此事件处理程序将被有效破坏。

要尝试这种情况,可以将hotKey属性移至AppDelegate。然后,该属性引用将存在很长一段时间(确切地说,直到您退出该应用程序为止)。

如果有帮助,我强烈建议您将逻辑封装在一个小帮手中。为了简单起见,可以将其存储为单例。

class HotKeyController {
    static var instance = HotKeyController()
    private init() { }

    var hotKey: HotKey? {
        didSet {
            hotKey.keyDownHandler = { [weak self] in
                NSApplication.shared.orderedWindows.forEach({ (window) in
                   print("woo")
                })
            }
        }
    }
}

然后在视图控制器中使用它:

class ViewController: NSViewController {

    @IBOutlet var pressedLabel: NSTextField!
    
    private var hotKey: HotKey? {
        get { 
            return HotKeyController.instance.hotKey
        }
        set {
            HotKeyController.instance.hotKey = newValue

            guard let hotKey = newValue else {
                pressedLabel.stringValue = "Unregistered"
                return
            }

            pressedLabel.stringValue = "Registered"
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        register(self)
        // Do any additional setup after loading the view.
    }
    
    @IBAction func unregister(_ sender: Any?) {
        hotKey = nil
        print("the hot key is ",hotKey?.keyCombo)
    }
    

    @IBAction func register(_ sender: Any) {
        hotKey = HotKey(keyCombo: KeyCombo(key: .j,modifiers: [.command,.shift]))
        print("the hot key is ",hotKey?.keyCombo)
    }
}

从长远来看,您将希望在UserDefaults的私有初始化程序中实现基于HotKeyController的热键存储和还原,以使设置“坚持”。