如何检索当前接收关键事件的OSX应用程序

Mar*_*kov 5 macos xcode cocoa swift

我正在关注cocoa文档以确定OSX中当前最前面的应用程序 - 也就是接收关键事件的应用程序.但是,当我执行以下swift时,API总是返回相同的值 - XCode但是chrome当我切换到它时,它永远不会更改为任何其他应用程序.我也尝试执行已编译的程序,但XCode现在不再显示它,而是显示我正在运行的终端应用程序.

确定从OSX接收关键事件的应用程序的正确方法是什么?我这方面的代码坏了吗?

import Cocoa

func getActiveApplication() -> String{
    // Return the localized name of the currently active application
    let ws = NSWorkspace.sharedWorkspace()
    let frontApp = ws.frontmostApplication
    return frontApp.localizedName
}

var frontMostApp : String
while true {
    frontMostApp = getActiveApplication();
    NSLog("front app: %@", frontMostApp)
    sleep(1);
}
Run Code Online (Sandbox Code Playgroud)

cha*_*142 5

这个帖子有点旧,但非常有帮助.我根据Marco的帖子和uchuugaka的回答做了一些研究.以下是结果.

// swift 3.0
// compile: xcrun -sdk macosx swiftc -framework Cocoa foo.swift -o foo
// run: ./foo

import Cocoa

class MyObserver: NSObject {
    override init() {
        super.init()
        NSWorkspace.shared().notificationCenter.addObserver(self, 
            selector: #selector(printMe(_:)), 
            name: NSNotification.Name.NSWorkspaceDidActivateApplication, 
            object:nil)
    }
    dynamic private func printMe(_ notification: NSNotification) {
        let app = notification.userInfo!["NSWorkspaceApplicationKey"] as! NSRunningApplication
        print(app.localizedName!)
    }
}
let observer = MyObserver()
RunLoop.main.run()
Run Code Online (Sandbox Code Playgroud)

我是Cocoa和Swift的新手.我不知道上述内容是否有效,但它对我有用.我从如何在swift 2命令行工具中创建最小守护进程获得了帮助Swift 3 NSNotificationCenter KeyboardWillshow /隐藏在众多其他人之间.

斯威夫特4:

NSWorkspace.shared.notificationCenter.addObserver(self,    // HERE, shared
    selector: #selector(printMe(_:)), 
    name: NSWorkspace.didActivateApplicationNotification,  // HERE
    object:nil)
Run Code Online (Sandbox Code Playgroud)

编辑(Swift 4)

编译器说printMe必须是函数@objc.(我不知道它的含义,但是当我@objc在行的开头添加时它就起作用.这是完整的代码,便于复制粘贴.

// swift 4.0
// compile: xcrun -sdk macosx swiftc -framework Cocoa foo.swift -o foo
// run: ./foo

import Cocoa

class MyObserver: NSObject {
    override init() {
        super.init()
        NSWorkspace.shared.notificationCenter.addObserver(self, 
            selector: #selector(printMe(_:)), 
            name: NSWorkspace.didActivateApplicationNotification, 
            object:nil)
    }
    @objc dynamic private func printMe(_ notification: NSNotification) {
        let app = notification.userInfo!["NSWorkspaceApplicationKey"] as! NSRunningApplication
        print(app.localizedName!)
    }
}
let observer = MyObserver()
RunLoop.main.run()
Run Code Online (Sandbox Code Playgroud)


uch*_*aka 3

您应该以不同的方式做一件事,那就是遵循 NSWorkSpace 通知,告诉您应用程序已退出活动状态或变为活动状态。这是关键,尤其是当您在调试模式下运行时。在调试模式下,Xcode 会将您的应用程序生成为子进程。在发布模式下,它基本上与在终端中调用 open 命令相同。在调试模式下,如果您太早调用此代码并且仅调用一次,则您将无法捕获更改。请记住它是动态的。