dun*_*anm 22 cocoa objective-c
我正在尝试确定哪个OSX应用程序当前处于活动状态.据我所知,在OSX 10.5中,可以通过以下方式完成:
[[NSWorkspace sharedWorkspace] activeApplication]
Run Code Online (Sandbox Code Playgroud)
但是,这已经在10.6+中被弃用了.
Apple开发人员文档指出,这应该通过NSRunningApplication对象的"active"属性来完成.我认为解决这个问题的一种方法可能是获取所有正在运行的应用程序的列表
[[NSWorkspace sharedWorkspace] runningApplications]
Run Code Online (Sandbox Code Playgroud)
然后循环,检查每个应用程序的"活动"属性.但是,以下测试代码的行为与我的预期不同:从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;
}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?我误解了"活跃"财产是如何运作的吗?
(另外,请随意批评我的Objective C代码---这是我在目标C上的第一次尝试,所以我知道它很可能对训练有素的眼睛很难看!请原谅我!:)欢迎任何建议.)
Lil*_*ard 20
您的问题是您的应用程序无法从系统接收任何事件,通知它当前应用程序已更改,因此它永远不会更新NSRunningApplication实例上的活动属性.如果我使用完全相同的代码,但是当我开始运行代码时,另一个应用程序处于活动状态,它会报告该应用程序.
相反,如果您更改代码以运行主线程NSRunLoop并使用1秒计时器,它应该工作.
这是一个简单的例子:
#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];
}
Run Code Online (Sandbox Code Playgroud)
NSG*_*God 17
每隔一秒左右轮询以查找当前的应用程序是低效的,并且这是错误的方法.更好的方法是简单地设置您的流程以接收NSWorkspaceDidActivateApplicationNotification通知.
@interface MDAppController : NSObject <NSApplicationDelegate> {
NSRunningApplication *currentApp;
}
@property (retain) NSRunningApplication *currentApp;
@end
@implementation MDAppController
@synthesize currentApp;
- (id)init {
if ((self = [super init])) {
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
selector:@selector(activeAppDidChange:)
name:NSWorkspaceDidActivateApplicationNotification object:nil];
}
return self;
}
- (void)dealloc {
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
[super dealloc];
}
- (void)activeAppDidChange:(NSNotification *)notification {
self.currentApp = [[notification userInfo] objectForKey:NSWorkspaceApplicationKey];
NSLog(@"currentApp == %@", currentApp);
}
@end
int main(int argc, const char * argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
MDAppController *appController = [[MDAppController alloc] init];
[NSApp setDelegate:appController];
[NSApp run];
[pool release];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
cod*_*nd1 12
从OS X 10.7开始NSWorkspace也有方便的方法:
- (NSRunningApplication *)frontmostApplication;
Run Code Online (Sandbox Code Playgroud)
此外,您现在可以使用Grand Central调度调用以超时进行重复调用.
像这样的东西:
- (void) checkFrontmostApp {
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSRunningApplication* runningApp = [[NSWorkspace sharedWorkspace] frontmostApplication];
//do something
NSLog(@"frontmost app: %@", runningApp.bundleIdentifier);
[self checkFrontmostApp]; //'recursive' call
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9626 次 |
| 最近记录: |