14

OSX ボックスでスクリーンセーバーとロック画面のイベントを監視したいと考えています。最初のパスとして、コンソールに出力するだけで問題ありません。

別の質問のアドバイスに従って、、、、、およびイベントのCocoa 通知com.apple.screensaver.didstartをリッスンする目的の C を書きました 。com.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
%

私の Objective C と Cocoa の知識は非常にさびしいので、フレームワークの使い方が間違っているのか、それとも間違ったイベントに登録したのか (また、それらが正しいイベントであるか、またはいいえ)。

それで、私が間違っているのは何ですか?

4

3 に答える 3

10

あなたはすでにあなたの問題をコメントしています。

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() から実行ループを作成してスピンするのは、非常に簡単なことです。クイック検索で利用可能な例がたくさんあります。

于 2013-06-05T18:15:46.607 に答える
2

com.apple.screensaver.* 通知がサポートされなくなったため、これに使用しようとしている戦略は機能しないようです。この同等の質問
への回答では、「Snow Leopard では、screenIsLocked および screenIsUnlocked 通知は利用できなくなりました。」と述べられています。 もちろん同じではありませんが、NSWorkspaceScreensDidSleepNotification 通知をリッスンするか、NSWorkspaceWillSleepNotification をリッスンしてコンピューターをスリープ状態にすることで、スクリーン スリープに登録できます。サンプル コードは、このフォーラムにあります。

補足: 名前に nil を使用すると、多くのイベントを受け取ります。

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

これを行うと、すべての種類のイベントを受け取りますが、スクリーンセーバーのものは受け取らないため、基本的にすべてを正しく行っていることがわかります。

于 2013-06-12T14:13:16.577 に答える