Objective-C:正在刷新 FrontmostApplication

Objective-C: Refreshing FrontmostApplication

我写了这个小程序,它应该打印两次当前最前面的应用程序,中间有 3 秒的中断。

void printFrontmostApp() {
    NSRunningApplication *frontmostApplication = [NSWorkspace sharedWorkspace].frontmostApplication;
    NSLog(@"%@",frontmostApplication);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        printFrontmostApp();
        sleep(3);
        printFrontmostApp();
    }
    return 0;
}

当我运行这个程序的时候,我发现frontmostApplication在第二次调用的时候并没有刷新。我找到了解决方案 。但是我还有两个问题:

1) 我想知道为什么 frontmostApplication 没有更新。

2) 如何在每次调用时强制刷新?我不想在最前面的应用程序每次停用时都收到通知,因为它对我的目的来说效率有点低。

编辑: 只是为了 crystal 清楚,我们假设现在的时间是 10:00:00。我调用 printFrontmostApp,它将 "Xcode" 打印到控制台,因为 Xcode 是当前最前面的应用程序。然后程序休眠 3 秒。在 10:00:01,我打开了另一个应用程序,比如 TextEdit。在 10:00:03,我的程序第二次调用 printFrontmostApp。我希望它打印 "TextEdit",这是当前最前面的应用程序。但它会打印 "Xcode" 。我无法理解这种行为。

有人可以解释一下 10:00:03 发生了什么吗?该函数似乎"remember" 10:00:00处​​的frontmostApplication的值,并在第二次调用时保留它。我以为任何内存一旦超出范围就会被释放,所以为什么会这样?

以及如何让我的程序在 10:00:03 处获得最前面的应用程序?我可以在 10:00:00 获得最前面的应用程序,我应该可以在 3 秒后做同样的事情吧?

对于 1) 的答案与您所链接的问题中描述的相同:您必须观察此通知,它告诉您新应用程序何时被激活:

NSWorkspaceDidActivateApplicationNotification

关于 2) 您有不同的激活和停用观察者,例如:

NSWorkspaceDidDeactivateApplicationNotification

因此您不会看到您未注册的通知,请查看 NSWorkspace Notifications 以获得完整列表。

否则,请定义您关于 refreshing/polling 的问题(我认为这无论如何都不是一个好主意)。

documentation for -[NSWorkspace runningApplications] — 不是您使用的方法,而是相关的 — 说:

Similar to the NSRunningApplication class’s properties, this property will only change when the main run loop is run in a common mode. Instead of polling, use key-value observing to be notified of changes to this array property.

来自NSRunningApplication documentation

Properties that vary over time are inherently race-prone. For example, a hidden app may unhide itself at any time. To ameliorate this, properties persist until the next turn of the main run loop in a common mode. For example, if you repeatedly poll an unhidden app for its hidden property without allowing the run loop to run, it will continue to return NO, even if the app hides, until the next turn of the run loop.

几乎可以肯定,同样的原则也适用于 -frontmostApplication,即使文档没有明确说明。在不允许 运行 循环到 运行.

的情况下,您永远不会通过轮询获得不同的结果