2012-04-17 4 views
0

私はブロックがNSDictionaryに格納されています。ブロックを更新するにはどうすればよいですか?

void(^RunningApplications)(void) = ^{ 
     NSArray *runningApps = [[NSWorkspace sharedWorkspace] runningApplications]; 
     NSMutableArray *appNames = [[NSMutableArray alloc] initWithCapacity:[runningApps count]]; 
     for (NSRunningApplication *app in runningApps) 
      [appNames addObject:[app localizedName]]; 
     NSLog(@"%@", [[NSWorkspace sharedWorkspace] runningApplications]); 
    }; 

私は現在NSLogを介して実行されているアプリケーションを参照してください。このブロックに初めてアクセス:これは、これらのブロックの一つです。しかし、別のアプリを開いてブロックを再度呼び出すと、新しく開かれたアプリで新しいリストではなく表示された元のリストだけが表示されます。このブロックを介して更新されたリストを受け取るにはどうすればよいですか?

答えて

3

あなたの問題は、ブロック(または辞書)と関係があり、あなたがどのようにして(ab)-runningApplicationsを使用しているかとは関係ありません。 docsから:NSRunningApplicationクラスのプロパティと同様に

、このプロパティ は本体のみ実行ループは共通モードで実行されたときに変更されます。 ポーリングの代わりに、キー値観測を使用して、 の変更がこの配列プロパティに通知されます。この目的を達成するために

、以下が適切な行動を示しています

#import "AppDelegate.h" 

const static NSString *runningApplicationsContext = @"running applications observation"; 

@implementation AppDelegate 

@synthesize window = _window; 

- (void)dealloc 
{ 
    [[NSWorkspace sharedWorkspace] removeObserver:self 
             forKeyPath:@"runningApplications" 
              context:&runningApplicationsContext]; 
    [super dealloc]; 
} 

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
    [[NSWorkspace sharedWorkspace] addObserver:self 
            forKeyPath:@"runningApplications" 
             options:NSKeyValueObservingOptionNew 
             context:&runningApplicationsContext]; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath 
         ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context 
{ 
    if (context == &runningApplicationsContext) { 
     NSArray *runningApps = [(NSWorkspace *)object runningApplications]; 
     NSMutableArray *appNames = [[NSMutableArray alloc] initWithCapacity:[runningApps count]]; 
     for (NSRunningApplication *app in runningApps) { 
      [appNames addObject:[app localizedName]]; 
     } 
     NSLog(@"%@", [[NSWorkspace sharedWorkspace] runningApplications]); 
     [appNames release]; 
    } 
} 

これは、別の素敵な利点があります:あなたは、場合にあなたが興味を持っている、通知をトリガ何アプリケーション(複数可)を決定するためにchange辞書を調べます。これにより、以前のrunningApplicationsの結果がキャッシング/トラッキングから解放されます。

EDIT:あなたのコメントにアップした後、ここにあなたのブロックでだけで正常に動作し、いくつかのコードは、(私はあなたの大きなアプリで何かをしたと推定デッドコードを剥奪)の辞書に保存されているとオブザーバメソッドから呼び出さ:

#import "AppDelegate.h" 

const static NSString *runningApplicationsContext = @"running applications observation"; 

@interface AppDelegate() { 
    NSDictionary *_blocks; 
} 

@end 

@implementation AppDelegate 

@synthesize window = _window; 

- (void)dealloc 
{ 
    [[NSWorkspace sharedWorkspace] removeObserver:self 
             forKeyPath:@"runningApplications" 
              context:&runningApplicationsContext]; 
    [_blocks release]; 
    [super dealloc]; 
} 

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
    _blocks = [[NSDictionary alloc] initWithObjectsAndKeys:(id) 
       ^{ 
        NSLog(@"%@", [[NSWorkspace sharedWorkspace] runningApplications]); 
       }, @"RunningApplications", 
       nil]; 

    [[NSWorkspace sharedWorkspace] addObserver:self 
            forKeyPath:@"runningApplications" 
             options:NSKeyValueObservingOptionNew 
             context:&runningApplicationsContext]; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath 
         ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context 
{ 
    if (context == &runningApplicationsContext) { 
     dispatch_block_t getRunningApplications = [_blocks objectForKey:@"RunningApplications"]; 
     getRunningApplications(); 
    } 
} 

@end 
+0

おかげさまで、ありがとうございました。私は 'runningApplications'のポーリングはこれを行う正しい方法ではないことを理解していますが、それが私が更新されたリストを取得していない理由ではないと私は信じています。以前にこのポーリングを行って更新リストを受け取った場合、問題は辞書からブロックにアクセスするときにのみ発生します。 – sud0

+0

ブロック・イン・ディクショナリを実装したコードを投稿しましたが、悪影響はありません。あなたの問題は、あなたのポーリング方法が何らかの形で実行ループの仮定を破っていることです。私があなたのコードをテストすると、例えばwhile()whileループでは、*動作しません。 –

+0

情報とコードについてもう一度おねがいします。将来のプログラムでこれを実装する予定ですが、現在の問題では十分ではありません。あなたのコードと私の唯一の違いは、新しいものが開かれたときにプログラムのリストを更新するのに対し、mineはユーザーの要求でリストを返すことです。しかし、最初のリクエストから受け取ったリストは、新しいアプリが開かれても、後続のリクエストに変更を加えることはありません。 – sud0

関連する問題