监控OSX中的屏幕保护程序事件

ram*_*ion 13 macos cocoa notifications objective-c screensaver

我想监视OSX盒子上的屏幕保护程序和锁屏事件.作为第一关,我很好,他们只是打印到控制台.

以下的其他人的问题的建议,我写了一些目标C监听可可通知的 com.apple.screensaver.didstart,com.apple.screensaver.didstop,com.apple.screenIsLocked,和com.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;
}
Run Code Online (Sandbox Code Playgroud)

它编译得很好,但是当我运行它时,我似乎没有观察到任何屏幕保护程序事件(尽管屏幕保护程序多次出现):

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

我的Objective C和Cocoa知识非常生疏,所以我不确定我是否使用了错误的框架,或者我是否注册了错误的事件(也不知道在哪里查看这些是正确的事件还是不).

那么我做错了什么?

Goa*_*Guy 10

你已经评论过你的问题了.

while(1); // busy wait's bad, I know, but easy to implement
Run Code Online (Sandbox Code Playgroud)

以上几乎总是一个坏主意.

NSDistributedNotificationCenter实际上需要运行主线程NSRunLoop才能运行.

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

从OS X上的命令行应用程序的main()创建和旋转运行循环是一件相当简单的事情.快速搜索有很多例子可供选择.

  • 实际上,我整理到单个源文件的我的调整版本可以在这里找到:http://pastie.org/8013106它包含一个修改后的构建命令,它在底部构建得更快,因为它链接到Foundation.framework而不是更大的Cocoa.framework(但要么应该工作正常) (3认同)

sza*_*yat 6

编辑:进一步测试显示com.apple.screensaver.didlaunch也可用,这里的代码在10.6.8和10.8.4上测试

如果[[NSRunLoop currentRunLoop] run];从Cocoa应用程序的applicationDidFinishLaunching:方法中删除并初始化ScreenSaverMonitor,则代码将起作用.(只需在XCode中创建一个新的Cocoa应用程序项目,并在适当的位置添加代码).

ScreenSaverMonitor.h

#import <Foundation/Foundation.h>

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

@end
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

AppDelegate.h

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

@interface AppDelegate : NSObject <NSApplicationDelegate>

@property (assign) IBOutlet NSWindow *window;
@property (retain) ScreenSaverMonitor *monitor;
@end
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

的main.m

#import <Cocoa/Cocoa.h>

int main(int argc, char *argv[])
{
    return NSApplicationMain(argc, (const char **)argv);
}
Run Code Online (Sandbox Code Playgroud)