什么是“正确的”方式来识别当前活动的应用程序在OSX 10.6+? [英] What is the 'correct' way to identify the currently active application in OSX 10.6+?

查看:112
本文介绍了什么是“正确的”方式来识别当前活动的应用程序在OSX 10.6+?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试识别哪个OSX应用程序当前处于活动状态。我理解在OSX 10.5中,可以这样做:

  [[NSWorkspace sharedWorkspace] activeApplication] 



但是,这已在10.6 +中被弃用。



开发人员文档声明这应该通过NSRunningApplication对象的'active'属性来完成。我认为一种方法可以通过

  [[NSWorkspace sharedWorkspace] runningApplications]获取所有正在运行的应用程序的列表。 b $ b  

,然后循环检查每个应用程序的active属性。但是,以下测试代码的行为不符合我的预期:从Terminal.app编译和运行时,只有终端应用程序被标记为活动,无论是否选择不同的应用程序。

  #import< Foundation / Foundation.h> 
#import< AppKit / NSRunningApplication.h>
#import< AppKit / NSWorkspace.h>

int main(int argc,char * argv []){
while(1){
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSString * currApp;
NSArray * runningApps;
runningApps = [[NSWorkspace sharedWorkspace] runningApplications];
for(id currApp in runningApps){
if([currApp isActive])
NSLog(@*%@,[currApp localizedName]);
else
NSLog(@%@,[currApp localizedName]);
}
sleep(1);
[pool release];
}

return 0;
}

我做错了什么?



(此外,请随意批评我的Objective C代码---这是我第一次尝试C的目标, )

解决方案

您的问题是,您的应用程序无法从系统接收任何事件通知它当前应用程序已更改,因此它从不更新 NSRunningApplication 实例的活动属性。如果我使用完全相同的代码,但另一个应用程序是活动的,当我开始运行代码,它报告该应用程序。



如果改为你的代码运行主线程的 NSRunLoop 并使用1秒定时器,它应该可以工作。



p>

  #import< Foundation / Foundation.h> 
#import< AppKit / AppKit.h>

@interface Foo:NSObject
- (void)run;
@end

@implementation Foo
- (void)run {
for(NSRunningApplication * currApp in [[NSWorkspace sharedWorkspace] runningApplications]){
if([currApp isActive]){
NSLog(@*%@,[currApp localizedName]);
} else {
NSLog(@%@,[currApp localizedName]);
}
}
NSLog(@---);
}
@end

int main(int argc,char * argv []){
NSAutoreleasePool * p = [NSAutoreleasePool new];

Foo * foo = [[Foo new] autorelease];
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:foo
selector:@selector(run)
userInfo:nil
重复:YES];
[[NSRunLoop mainRunLoop] run];

[p release];
}


I'm trying to identify which OSX application is currently active. I understand that in OSX 10.5, this could be done with:

[[NSWorkspace sharedWorkspace] activeApplication]

however, this has been deprecated in 10.6+.

The apple developers documentation states that this should be done through the 'active' property of the NSRunningApplication object. I thought one way to approach this might be to get the list of all running applications through

[[NSWorkspace sharedWorkspace] runningApplications]

and then loop through, checking the 'active' property of each application. However, the following test code doesn't behave as I expected: when compiled and run from Terminal.app, only the "terminal" app is ever marked as active, regardless of whether I select a different application.

#import <Foundation/Foundation.h>
#import <AppKit/NSRunningApplication.h>
#import <AppKit/NSWorkspace.h>

int main(int argc, char *argv[]) {
  while(1){
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSString *currApp;
    NSArray *runningApps;
    runningApps = [[NSWorkspace sharedWorkspace] runningApplications];
    for (id currApp in runningApps) {
      if ([currApp isActive])
          NSLog(@"* %@", [currApp localizedName]);
      else
          NSLog(@"  %@", [currApp localizedName]);
    }
    sleep(1);
    [pool release];
  }

  return 0;
}

What am I doing wrong? Have I misunderstood how the "active" property works?

(Also, please feel free to criticise my Objective C code --- this is my first attempt at objective C, so I know it's likely to be hideously ugly to the trained eye! Please forgive me! :) Any suggestions welcome.)

解决方案

Your problem is that your application is unable to receive any events from the system informing it that the current application has changed, and therefore it never updates the active property on the NSRunningApplication instances. If I use the exact same code, but another app is active when I start running the code, it reports that application instead.

If instead you change your code to run the main thread's NSRunLoop and use a 1-second timer, it should work.

Here's a quick example:

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

@interface Foo : NSObject
- (void)run;
@end

@implementation Foo
- (void)run {
    for (NSRunningApplication *currApp in [[NSWorkspace sharedWorkspace] runningApplications]) {
        if ([currApp isActive]) {
            NSLog(@"* %@", [currApp localizedName]);
        } else {
            NSLog(@"  %@", [currApp localizedName]);
        }
    }
    NSLog(@"---");
}
@end

int main(int argc, char *argv[]) {
    NSAutoreleasePool *p = [NSAutoreleasePool new];

    Foo *foo = [[Foo new] autorelease];
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
                                                      target:foo
                                                    selector:@selector(run)
                                                    userInfo:nil
                                                     repeats:YES];
    [[NSRunLoop mainRunLoop] run];

    [p release];
}

这篇关于什么是“正确的”方式来识别当前活动的应用程序在OSX 10.6+?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆