0

にブロックが保存されていNSDictionaryます。これはそれらのブロックの 1 つです。

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。ただし、別のアプリを開いてブロックを再度呼び出すと、新しく開いたアプリの新しいリストではなく、表示された元のリストのみが表示されます。このブロックを介して更新されたリストを受け取るにはどうすればよいですか?

4

1 に答える 1

3

あなたの問題はブロック(または辞書)とは何の関係もなく、あなたがどのように(ab)使用しているかと関係があります-runningApplicationsドキュメントから:

NSRunningApplicationクラスのプロパティと同様に、このプロパティは、メインの実行ループが共通モードで実行されている場合にのみ変更されます。ポーリングの代わりに、Key-Value監視を使用して、この配列プロパティへの変更が通知されます。

この目的のために、以下は適切な動作を示しています。

#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];
    }
}

これにはもう1つの優れた利点changeがあります。興味がある場合は、辞書を調べて、通知をトリガーしたアプリケーションを特定します。これにより、以前の結果をキャッシュ/追跡する必要がなくなりますrunningApplications

編集:あなたのコメントに続いて、辞書に保存され、オブザーバーメソッドから呼び出されたブロック(私があなたのより大きなアプリで何かをしたと私が推測するデッドコードを取り除いた)でうまく機能するいくつかのコードがあります:

#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
于 2012-04-17T02:12:51.953 に答える