如何在 Swift5 中监听 keydown 事件?

Posted

技术标签:

【中文标题】如何在 Swift5 中监听 keydown 事件?【英文标题】:How do I listen for a keydown event in Swift5? 【发布时间】:2020-02-12 21:27:59 【问题描述】:

我试图在我的 MacOS 应用程序深处的 SwiftUI 视图中捕获 KeyDown 事件。但是,我什至无法在 AppDelegate 中触发一个。

这是我现在正在尝试的:

import Cocoa
import SwiftUI

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate 
    var window: NSWindow!
    var settings = UserSettings()

    func keyDown(theEvent: NSEvent) 
        if (theEvent.keyCode == 1)
            print("test")
        
    

    func applicationDidFinishLaunching(_ aNotification: Notification) 

        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView().environmentObject(settings)

        // Create the window and set the content view. 
        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    

    func applicationWillTerminate(_ aNotification: Notification) 
        // Insert code here to tear down your application
    


我还能如何解决这个问题?

【问题讨论】:

这不是应用委托的工作......你应该在你的一个 VC 中实现 keyDown @Alexander-ReinstateMonica 不一定。你甚至可能没有窗户***.com/a/59592581/2303865 @LeoDabus 应用代理是否在响应者链中? @Willeke developer.apple.com/library/archive/documentation/Cocoa/… @LeoDabus See Responder Chain for Event Messages "第一个响应者通常是窗口中的“选定”视图对象,它的下一个响应者是它的包含视图(也称为它的父视图),依此类推直到NSWindow 对象。如果一个 NSWindowController 对象正在管理窗口,它将成为最终的下一个响应者。”。应用委托在哪里? 【参考方案1】:

您可以“安装”您自己的处理程序(参见 window.trackEvents ...)

import Cocoa
import SwiftUI

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate 

    var window: NSWindow!

    func applicationDidFinishLaunching(_ aNotification: Notification) 
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()

        // Create the window and set the content view. 
        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
        window.trackEvents(matching: .keyDown, timeout: .infinity, mode: RunLoop.Mode.default)  (event, _) in
            print(event)
        
    

    func applicationWillTerminate(_ aNotification: Notification) 
        // Insert code here to tear down your application
    



这是一些打印示例

Optional(NSEvent: type=KeyDown loc=(116.223,179.594) time=38176.8 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="h" unmodchars="h" repeat=0 keyCode=4)
Optional(NSEvent: type=KeyDown loc=(116.223,179.594) time=38178.2 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="j" unmodchars="j" repeat=0 keyCode=38)
Optional(NSEvent: type=KeyDown loc=(116.223,179.594) time=38178.9 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="h" unmodchars="h" repeat=0 keyCode=4)
Optional(NSEvent: type=KeyDown loc=(116.223,179.594) time=38179.4 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="g" unmodchars="g" repeat=0 keyCode=5)
Optional(NSEvent: type=KeyDown loc=(116.223,179.594) time=38179.9 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="h" unmodchars="h" repeat=0 keyCode=4)
Optional(NSEvent: type=KeyDown loc=(108.574,-175.18) time=38184.5 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="m" unmodchars="m" repeat=0 keyCode=46)
Optional(NSEvent: type=KeyDown loc=(108.574,-175.18) time=38184.8 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="," unmodchars="," repeat=0 keyCode=43)
Optional(NSEvent: type=KeyDown loc=(108.574,-175.18) time=38185.1 flags=0x100 win=0x11b830710 winNum=2404 ctxt=0x0 chars="." unmodchars="." repeat=0 keyCode=47)

请担心!这是最简单的例子,在实际应用程序中,您的处理程序必须处理所有 keyDown 事件!正如本例中所做的那样,默认操作(菜单...等)不会做出反应。您甚至必须从您的 Xcode(或终端)中停止应用程序,或者从系统菜单中强制退出它

【讨论】:

以上是关于如何在 Swift5 中监听 keydown 事件?的主要内容,如果未能解决你的问题,请参考以下文章

jQuery监听键盘事件及相关操作使用

jq 监听键盘事件

为什么RxJS主题比多个事件监听器更快?

JavaScript监听键盘事件

JavaScript监听键盘事件

关于键盘事件