cocoa - 我怎样才能更新我的 block ?

标签 cocoa block

我有存储在 NSDictionary 中的 block 。这是这些 block 之一:

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

第一次访问此 block 时,我看到当前正在通过 NSLog 运行的应用程序。但是,如果我打开另一个应用程序,然后再次调用该 block ,我只会看到显示的原始列表,而不是包含新打开的应用程序的新列表。我如何通过此 block 接收更新的列表?

最佳答案

您的问题与 block (或字典)无关,而与您如何(ab)使用-runningApplications有关。来自 docs :

Similar to the NSRunningApplication class’s properties, this property will only change when the main run loop is run in a common mode. Instead of polling, use key-value observing to be notified of changes to this array property.

为此,以下演示了正确的行为:

#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 结果。

编辑:根据您的评论,这里有一些代码可以与您的 block 一起正常工作(删除了我认为在您的较大应用程序中执行某些操作的死代码)存储在字典中并从观察者方法调用:

#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

关于cocoa - 我怎样才能更新我的 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10184022/

相关文章:

cocoa - AppKit 控件的视觉指南?

ios - 新的 Apple SDK 是否会修补以前的版本?

ios - 定义后立即调用 block

iphone - 在类内部将 block 作为类中的属性转发

ios - 阻止 ios : what is this method map: before a block?

c# - 在 c# 2.0 中阻止/重定向 IP 或没有主机文件的主机

python - block 中的 block

xcode - 在cocoa应用程序中创建菜单和子菜单

macos - (Mac) 将 NSWindowController 的窗口更改为 NSWindow 的子类

cocoa - cocoa 的面包屑导航