2013-06-05 55 views
12

我想監視OSX框上的屏幕保護程序和鎖定屏幕事件。作爲第一遍,我很好,他們只是打印到控制檯。在OSX中監視屏幕保護程序事件

the advice of another's question,我寫了一些目標C監聽可可通知的 com.apple.screensaver.didstartcom.apple.screensaver.didstopcom.apple.screenIsLockedcom.apple.screenIsUnlocked事件。

// ScreenSaverMonitor.h 
#import <Foundation/NSObject.h> 
#import <Foundation/NSNotification.h> 

@interface ScreenSaverMonitor: NSObject {} 
-(id) init; 
-(void) receive: (NSNotification*) notification; 
@end 

// ScreenSaverMonitor.m 
#import "ScreenSaverMonitor.h" 
#import <Foundation/NSString.h> 
#import <Foundation/NSDistributedNotificationCenter.h> 
#import <Foundation/NSRunLoop.h> 
#import <stdio.h> 

@implementation ScreenSaverMonitor 
-(id) init { 
    NSDistributedNotificationCenter * center 
    = [NSDistributedNotificationCenter defaultCenter]; 

    [center addObserver: self 
      selector: @selector(receive:) 
      name:  @"com.apple.screensaver.didstart" 
      object:  nil 
    ]; 
    [center addObserver: self 
      selector: @selector(receive:) 
      name:  @"com.apple.screensaver.didstop" 
      object:  nil 
    ]; 
    [center addObserver: self 
      selector: @selector(receive:) 
      name:  @"com.apple.screenIsLocked" 
      object:  nil 
    ]; 
    [center addObserver: self 
      selector: @selector(receive:) 
      name:  @"com.apple.screenIsUnlocked" 
      object:  nil 
    ]; 
    printf("running loop... (^C to quit)"); 
    [[NSRunLoop currentRunLoop] run]; 
    printf("...ending loop"); 
    return self; 
} 
-(void) receive: (NSNotification*) notification { 
    printf("%s\n", [[notification name] UTF8String]); 
} 
@end 

// ScreenSaverMonitorMain.m 
#import "ScreenSaverMonitor.h" 

int main(int argc, char ** argv) { 
    [[ScreenSaverMonitor alloc] init]; 
    return 0; 
} 

它編譯罰款,但是當我運行它,我似乎並沒有觀察到任何屏幕事件(儘管有屏幕保護程序來上多次):

% gcc -Wall ScreenSaverMonitor.m ScreenSaverMonitorMain.m -o ScreenSaverMonitor -lobjc -framework Cocoa 
% ./ScreenSaverMonitor 
running loop (^C to quit)... 
^C 
% 

我的目標C和Cocoa知識是非常生疏的,所以我不確定我是否錯誤地使用了框架,或者如果我註冊了錯誤的事件(也不知道在哪裏查找是否是正確的事件)。

那麼我在做什麼錯了?

回答

9

您已經評論過您的問題。

while(1); // busy wait's bad, I know, but easy to implement 

以上幾乎總是一個壞主意。

NSDistributedNotificationCenter實際上需要一個運行的主線程NSRunLoop才能運行。

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Notifications/Articles/NotificationCenters.html#//apple_ref/doc/uid/20000216-BAJGDAFC

創建和從OS X的命令行應用程序的main()中紡運行循環是一個相當簡單的事情。有很多快速搜索的例子。

+0

好主意!我用'[[NSRunLoop currentRunLoop] run]'替換了'while(1);',但仍然沒有骰子。 – rampion

+0

我不確定你在這裏遇到什麼。我已經採取了上面的編輯代碼,修復了一個編譯器錯誤,並做了輕微的日誌記錄更改,並且它對我來說似乎工作正常。具體來說,我將#import 行更改爲#import ,並將printf語句更改爲fprintf stderr。 (這個效果更好,因爲stderr是立即刷新的,而不是像printf那樣緩衝。 – GoannaGuy

+2

實際上,我整理到單個源文件中的我的調整版本可以在這裏找到:http://pastie.org/8013106它包含一個修改後的版本命令在底部建立一點快,因爲它鏈接到Foundation.framework而不是較大的Cocoa.framework(但任一個都應該可以正常工作) – GoannaGuy

2

看起來您嘗試使用的策略無效,因爲不再支持com.apple.screensaver。*通知。
在對this equivalent question的回覆中提到:'對於Snow Leopard,screenIsLocked和screenIsUnlocked通知不再可用。
通過偵聽NSWorkspaceScreensDidSleepNotification通知或者通過偵聽NSWorkspaceWillSleepNotification使計算機進入睡眠狀態,您可以註冊屏幕睡眠,當然這不同於屏幕睡眠,但可能是您可以接受的替代方法。示例代碼可以找到on this forum

旁註:如果你使用零的名字,你會收到很多的事件:

[center addObserver:self 
      selector:@selector(receive:) 
       name:nil 
      object:nil 
]; 

如果你這樣做,你會看到你正在做的一切基本上是正確的,因爲你會收到所有種類的事件 - 但沒有屏幕保護程序。

+1

從10.10開始,仍然發送com.apple.screensaver。*通知(與screenIsLocked/screenIsUnlocked一樣)。此外,'NSDistributedNotificationCenter'不會讓您註冊所有通知,至少在沙盒應用程序中。你會收到警告,「***試圖註冊沙盒阻止的所有分佈式通知。」 – zpasternack

5

編輯:進一步測試表明,com.apple.screensaver.didlaunch也可,這裏的代碼是在10.6.8和10.8.4測試

,如果你從Cocoa應用程序的applicationDidFinishLaunching:方法去除[[NSRunLoop currentRunLoop] run];和 初始化ScreenSaverMonitor你的代碼將工作。 (只需在XCode中創建一個新的Cocoa應用程序項目並在適當的地方添加您的代碼)。

ScreenSaverMonitor。ħ

#import <Foundation/Foundation.h> 

@interface ScreenSaverMonitor : NSObject 
-(id) init; 
-(void) receive: (NSNotification*) notification; 

@end 

ScreenSaverMonitor.m

#import "ScreenSaverMonitor.h" 
#import <Foundation/NSString.h> 
#import <Foundation/NSDistributedNotificationCenter.h> 
#import <Foundation/NSRunLoop.h> 
#import <stdio.h> 

@implementation ScreenSaverMonitor 
-(id) init { 
    NSDistributedNotificationCenter * center 
    = [NSDistributedNotificationCenter defaultCenter]; 

    [center addObserver: self 
       selector: @selector(receive:) 
        name:  @"com.apple.screensaver.didlaunch" 
       object:  nil 
    ]; 

    [center addObserver: self 
       selector: @selector(receive:) 
        name:  @"com.apple.screensaver.didstart" 
       object:  nil 
    ]; 
    [center addObserver: self 
       selector: @selector(receive:) 
        name:  @"com.apple.screensaver.didstop" 
       object:  nil 
    ]; 
    [center addObserver: self 
       selector: @selector(receive:) 
        name:  @"com.apple.screenIsLocked" 
       object:  nil 
    ]; 
    [center addObserver: self 
       selector: @selector(receive:) 
        name:  @"com.apple.screenIsUnlocked" 
       object:  nil 
    ]; 
    return self; 
} 
-(void) receive: (NSNotification*) notification { 
    printf("%s\n", [[notification name] UTF8String]); 
} 

@end 

AppDelegate.h

#import <Cocoa/Cocoa.h> 
#import "ScreenSaverMonitor.h" 

@interface AppDelegate : NSObject <NSApplicationDelegate> 

@property (assign) IBOutlet NSWindow *window; 
@property (retain) ScreenSaverMonitor *monitor; 
@end 

AppDelegate.m

#import "AppDelegate.h" 
#import "ScreenSaverMonitor.h" 

@implementation AppDelegate 
@synthesize monitor; 
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
    // Insert code here to initialize your application 
    self.monitor = [[ScreenSaverMonitor alloc] init]; 

} 

@end 

的main.m

#import <Cocoa/Cocoa.h> 

int main(int argc, char *argv[]) 
{ 
    return NSApplicationMain(argc, (const char **)argv); 
} 
相關問題