请问 Swift 如何动态注册快捷键?

2019-05-16 09:02:06 +08:00
 justdoit123

之前写了一个注册快捷键(写死在代码里)的 mac 工具,用来调用 AppleScript,实在不熟悉 swift,所以后来写了一个 Electronjs 版本的。

但是,但是,但是 mac 升级到 10.14 后,nodejs 里调用 AppleScript 变得非常慢!会有 2~3 秒的延迟,泪目。

今天尝试了一下 swift 版本,貌似延迟小了很多,但是我不懂如何实现像 nodejs 那样加载一个配置文件,然后在代码里动态注册好所有快捷键。

google 了很久,都是些如何注册快捷键的问题。

swift 大神,看了我的代码之后,劳烦指引个方向。

//
//  AppDelegate.swift
//  hotkey-watcher
//
//  Created by MistKafka on 2018/5/5.
//  Copyright © 2018 MistKafka. All rights reserved.
//

struct Keycode {

    // Layout-independent Keys
    // eg.These key codes are always the same key on all layouts.
    static let returnKey                 : UInt16 = 0x24
    static let enter                     : UInt16 = 0x4C
    static let tab                       : UInt16 = 0x30
    static let space                     : UInt16 = 0x31
    static let delete                    : UInt16 = 0x33
    static let escape                    : UInt16 = 0x35
    static let command                   : UInt16 = 0x37
    static let shift                     : UInt16 = 0x38
    static let capsLock                  : UInt16 = 0x39
    static let option                    : UInt16 = 0x3A
    static let control                   : UInt16 = 0x3B
    static let rightShift                : UInt16 = 0x3C
    static let rightOption               : UInt16 = 0x3D
    static let rightControl              : UInt16 = 0x3E
    static let leftArrow                 : UInt16 = 0x7B
    static let rightArrow                : UInt16 = 0x7C
    static let downArrow                 : UInt16 = 0x7D
    static let upArrow                   : UInt16 = 0x7E
    static let volumeUp                  : UInt16 = 0x48
    static let volumeDown                : UInt16 = 0x49
    static let mute                      : UInt16 = 0x4A
    static let help                      : UInt16 = 0x72
    static let home                      : UInt16 = 0x73
    static let pageUp                    : UInt16 = 0x74
    static let forwardDelete             : UInt16 = 0x75
    static let end                       : UInt16 = 0x77
    static let pageDown                  : UInt16 = 0x79
    static let function                  : UInt16 = 0x3F
    static let f1                        : UInt16 = 0x7A
    static let f2                        : UInt16 = 0x78
    static let f4                        : UInt16 = 0x76
    static let f5                        : UInt16 = 0x60
    static let f6                        : UInt16 = 0x61
    static let f7                        : UInt16 = 0x62
    static let f3                        : UInt16 = 0x63
    static let f8                        : UInt16 = 0x64
    static let f9                        : UInt16 = 0x65
    static let f10                       : UInt16 = 0x6D
    static let f11                       : UInt16 = 0x67
    static let f12                       : UInt16 = 0x6F
    static let f13                       : UInt16 = 0x69
    static let f14                       : UInt16 = 0x6B
    static let f15                       : UInt16 = 0x71
    static let f16                       : UInt16 = 0x6A
    static let f17                       : UInt16 = 0x40
    static let f18                       : UInt16 = 0x4F
    static let f19                       : UInt16 = 0x50
    static let f20                       : UInt16 = 0x5A

    // US-ANSI Keyboard Positions
    // eg. These key codes are for the physical key (in any keyboard layout)
    // at the location of the named key in the US-ANSI layout.
    static let a                         : UInt16 = 0x00
    static let b                         : UInt16 = 0x0B
    static let c                         : UInt16 = 0x08
    static let d                         : UInt16 = 0x02
    static let e                         : UInt16 = 0x0E
    static let f                         : UInt16 = 0x03
    static let g                         : UInt16 = 0x05
    static let h                         : UInt16 = 0x04
    static let i                         : UInt16 = 0x22
    static let j                         : UInt16 = 0x26
    static let k                         : UInt16 = 0x28
    static let l                         : UInt16 = 0x25
    static let m                         : UInt16 = 0x2E
    static let n                         : UInt16 = 0x2D
    static let o                         : UInt16 = 0x1F
    static let p                         : UInt16 = 0x23
    static let q                         : UInt16 = 0x0C
    static let r                         : UInt16 = 0x0F
    static let s                         : UInt16 = 0x01
    static let t                         : UInt16 = 0x11
    static let u                         : UInt16 = 0x20
    static let v                         : UInt16 = 0x09
    static let w                         : UInt16 = 0x0D
    static let x                         : UInt16 = 0x07
    static let y                         : UInt16 = 0x10
    static let z                         : UInt16 = 0x06

    static let zero                      : UInt16 = 0x1D
    static let one                       : UInt16 = 0x12
    static let two                       : UInt16 = 0x13
    static let three                     : UInt16 = 0x14
    static let four                      : UInt16 = 0x15
    static let five                      : UInt16 = 0x17
    static let six                       : UInt16 = 0x16
    static let seven                     : UInt16 = 0x1A
    static let eight                     : UInt16 = 0x1C
    static let nine                      : UInt16 = 0x19

    static let equals                    : UInt16 = 0x18
    static let minus                     : UInt16 = 0x1B
    static let semicolon                 : UInt16 = 0x29
    static let apostrophe                : UInt16 = 0x27
    static let comma                     : UInt16 = 0x2B
    static let period                    : UInt16 = 0x2F
    static let forwardSlash              : UInt16 = 0x2C
    static let backslash                 : UInt16 = 0x2A
    static let grave                     : UInt16 = 0x32
    static let leftBracket               : UInt16 = 0x21
    static let rightBracket              : UInt16 = 0x1E

    static let keypadDecimal             : UInt16 = 0x41
    static let keypadMultiply            : UInt16 = 0x43
    static let keypadPlus                : UInt16 = 0x45
    static let keypadClear               : UInt16 = 0x47
    static let keypadDivide              : UInt16 = 0x4B
    static let keypadEnter               : UInt16 = 0x4C
    static let keypadMinus               : UInt16 = 0x4E
    static let keypadEquals              : UInt16 = 0x51
    static let keypad0                   : UInt16 = 0x52
    static let keypad1                   : UInt16 = 0x53
    static let keypad2                   : UInt16 = 0x54
    static let keypad3                   : UInt16 = 0x55
    static let keypad4                   : UInt16 = 0x56
    static let keypad5                   : UInt16 = 0x57
    static let keypad6                   : UInt16 = 0x58
    static let keypad7                   : UInt16 = 0x59
    static let keypad8                   : UInt16 = 0x5B
    static let keypad9                   : UInt16 = 0x5C
}

import Cocoa
import Magnet

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    @IBOutlet weak var window: NSWindow!
    let switchToSafariScript = NSAppleScript(source: "tell application \"Safari\" to activate")
    let switchToTerminalScript = NSAppleScript(source: "tell application \"Terminal\" to activate")
    let switchToChromeScript = NSAppleScript(source: "tell application \"Google Chrome\" to activate")
    let switchToEmacsScript = NSAppleScript(source: "tell application \"Emacs\" to activate")
    let switchToEmacsGitScript = NSAppleScript(source: "tell application \"Emacs-for-Git\" to activate")
    let switchToPycharmScript = NSAppleScript(source: "tell application \"PyCharm\" to activate")


    
    func applicationDidFinishLaunching(_ aNotification: Notification) {

        guard let keyCombo1 = KeyCombo(keyCode: Int(Keycode.s), cocoaModifiers: [.shift, .control, .command, .option]) else { return }
        let hotKey1 = HotKey(identifier: "switch-to-safari",
            keyCombo: keyCombo1,
            target: self,
            action: #selector(AppDelegate.switchToSafari))
        hotKey1.register()
        
        guard let keyCombo2 = KeyCombo(keyCode: Int(Keycode.t), cocoaModifiers: [.shift, .control, .command, .option]) else { return }
        let hotKey2 = HotKey(identifier: "switch-to-terminal",
                             keyCombo: keyCombo2,
                             target: self,
                             action: #selector(AppDelegate.switchToTerminal))
        hotKey2.register()
        
        guard let keyCombo3 = KeyCombo(keyCode: Int(Keycode.c), cocoaModifiers: [.shift, .control, .command, .option]) else { return }
        let hotKey3 = HotKey(identifier: "switch-to-chrome",
                             keyCombo: keyCombo3,
                             target: self,
                             action: #selector(AppDelegate.switchToChrome))
        hotKey3.register()
        
        
        guard let keyCombo5 = KeyCombo(keyCode: Int(Keycode.e), cocoaModifiers: [.shift, .control, .command, .option]) else { return }
        let hotKey5 = HotKey(identifier: "switch-to-emacs",
                             keyCombo: keyCombo5,
                             target: self,
                             action: #selector(AppDelegate.switchToEmacs))
        hotKey5.register()
        
        guard let keyCombo6 = KeyCombo(keyCode: Int(Keycode.g), cocoaModifiers: [.shift, .control, .command, .option]) else { return }
        let hotKey6 = HotKey(identifier: "switch-to-emacs-git",
                             keyCombo: keyCombo6,
                             target: self,
                             action: #selector(AppDelegate.switchToEmacsGit))
        hotKey6.register()
        
        guard let keyCombo7 = KeyCombo(keyCode: Int(Keycode.p), cocoaModifiers: [.shift, .control, .command, .option]) else { return }
        let hotKey7 = HotKey(identifier: "switch-to-pycharm",
                             keyCombo: keyCombo7,
                             target: self,
                             action: #selector(AppDelegate.switchToPycharm))
        hotKey7.register()
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }
    
    @objc func switchToSafari() {
        self.switchTo(script: self.switchToSafariScript!)
    }
    @objc func switchToTerminal() {
        self.switchTo(script: self.switchToTerminalScript!)
    }
    @objc func switchToChrome() {
        self.switchTo(script: self.switchToChromeScript!)
    }
    @objc func switchToEmacs() {
        self.switchTo(script: self.switchToEmacsScript!)
    }
    @objc func switchToEmacsGit() {
        self.switchTo(script: self.switchToEmacsGitScript!)
    }
    @objc func switchToPycharm() {
        self.switchTo(script: self.switchToPycharmScript!)
    }
    
    func switchTo(script: NSAppleScript) {
        var error: NSDictionary?
        if let output: NSAppleEventDescriptor = script.executeAndReturnError(&error) {
            print(output.stringValue ?? "success!")
        } else {
            print("error: \(String(describing: error))")
        }
    }
}

4370 次点击
所在节点    Swift
2 条回复
ioschen
2019-05-16 10:17:44 +08:00
justdoit123
2019-05-16 11:22:48 +08:00
@ioschen 好,谢谢。我回去看看。

这种动态需求,是不是要用闭包?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/564560

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX