2

我编写了这个小程序,它应该打印两次当前最前面的应用程序,中间有 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)每次调用时如何强制刷新?我不想在最前面的应用程序每次停用时都收到通知,因为它对我的目的来说效率有点低。

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

有人可以解释一下 10:00:03 发生了什么吗?该函数似乎“记住”了 frontmostApplication 在 10:00:00 的值,并在第二次调用时保留它。我认为一旦超出范围,任何内存都会被释放,那么为什么会发生这种情况呢?

以及如何让我的程序在 10:00:03 获得最前面的应用程序?我可以在 10:00:00 获得最前面的应用程序,我应该能够在 3 秒后执行相同的操作,对吧?

4

2 回答 2

1

文档-[NSWorkspace runningApplications]——不是你使用的方法,而是相关的——说:

NSRunningApplication类的属性类似,该属性只有在主运行循环以普通模式运行时才会改变。使用键值观察来通知此数组属性的更改,而不是轮询。

NSRunningApplication文档中:

随时间变化的属性本质上是容易竞争的。例如,隐藏的应用程序可能随时取消隐藏。为了改善这一点,属性会一直持续到下一轮以公共模式运行的主运行循环。例如,如果您在不允许运行循环运行的情况下重复轮询未隐藏的应用程序的隐藏属性NO,即使应用程序隐藏,它也会继续返回,直到运行循环的下一轮。

-frontmostApplication几乎可以肯定,即使文档没有明确说明,同样的原则也适用。如果不允许运行循环运行,您将永远不会通过轮询获得不同的结果。

于 2015-10-28T15:41:01.323 回答
1

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

NSWorkspaceDidActivateApplicationNotification

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

NSWorkspaceDidDeactivateApplicationNotification

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

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

于 2015-10-28T14:12:03.513 回答