2009-07-09 102 views
19

是否有可能观察(订阅)存储在NSMutableDictionary中不同键上的值的更改?在我的情况下,订阅启动时密钥已经存在,但值改变,我希望在这种情况下得到通知。我希望通知中已更改值的关键字。观察NSMutableDictionary更改

我假设如果我的字典键都是NSString实例,我可以单独订阅每个关键路径。但是如果我的密钥不是字符串呢?在这种情况下,我运气不好吗?

回答

6

这是一个有趣的想法。我无法找到任何看起来很有希望的NSDictionary或NSDictionaryController。我的第一本能是围绕一个NSMutableDictionary使用组合,并拦截对setObject:forKey:的调用(也许-removeObjectForKey :)来通知订阅者的变化。

有一个关于子类化NSMutableDictionary的Cocoa With Love post,如果你选择去那条路线,这可能会很有用。我也有created my own NSMutableDictionary subclasses,欢迎您使用开源代码。

您可以设计一个观察者协议,该协议可以指定应该监视的特定键。不应该是太多的代码,但现在比我有时间放弃更多的代码。

+0

谢谢。我认为围绕NSMutableDictionary的构成是一条路。除非键是NSStrings,否则我仍然无法看到如何完成这项工作,但我认为我可以使用它。 – 2009-07-10 06:52:14

+0

@奎因泰勒:你的自定义子类的链接似乎已经死了,我需要检查这个代码。你还有它挂在什么地方? – Cyrille 2012-08-10 09:13:53

6

我已经成功地实现了这一点,使用围绕NSMutableDictionary的组合。我很惊讶它只需要很少的代码。我实施的班级是董事会,用于代表棋盘游戏中的模型。任何人都可以通过调用的addObserver订阅的板状态的变化:方法,实现这样的:

- (void)addObserver:(id)observer { 
    for (id key in grid) 
     [self addObserver:observer 
       forKeyPath:[key description] 
        options:0 
        context:key]; 
} 

既然你只能订阅使用KVO模式键,我被骗了,并订阅了关键的描述 ,而是将密钥本身作为上下文。在观察我的主板实例的对象中,我实现了-observeValueForKeyPath:ofObject:change:context:来忽略keyPath字符串,并使用传入的上下文。

我简单的电路板级不符合志愿为创建使用这种方法人工性质的,所以我在options属性传递0所以志愿机器不会试图获得这些密钥的旧/新值。这会导致我的代码炸毁。

任何改变电路板(在我的简单的类,只有一个方法,这是否)筹集必要的通知,导致KVO机械跃入行动:

- (void)setPiece:(id)piece atLocation:(Location*)loc { 
    [self willChangeValueForKey:[loc description]]; 
    [grid setObject:piece forKey:loc]; 
    [self didChangeValueForKey:[loc description]]; 
} 

瞧!使用非字符串键订阅NSMutableDictionary!