NSMutableDictionary KVO

Joh*_*igg 5 objective-c key-value-observing

我正在尝试使用KVO观察字典中的变化.

例:

dictionary = [NSMutableDictionary new];
[dictionary setObject:@"test1" forKey:@"key1"];
[dictionary setObject:@"test2" forKey:@"key2"];    
[dictionary setObject:@"test3" forKey:@"key1"];
Run Code Online (Sandbox Code Playgroud)

我希望无论何时将值添加到字典中,都能够挂钩观察者.删除或替换(即在上述情况下,无论何时调用任何setObject方法)

总而言之:我想要一个功能

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
Run Code Online (Sandbox Code Playgroud)

当我向字典添加任何新条目,或删除任何条目,或者替换任何条目时调用.

NOT:我不想指定我正在观察的键.(例如,仅在添加@"key1"时观察),因为此解决方案无法缩放.

gai*_*ige 8

子类化NSMutableDictionary有点烦人,因为NSDictionary及其朋友是类集群.它肯定是可行的,如果你必须将对象本身传递给另一组类,那么你可能想要做到这一点.否则,可能更容易创建具有相同基本API的复合类,并在内部使用NSMutableDictionary对象进行存储.有一个非常好的写作CocoaWithLove.com,Ordered Dictionary Subclassing,这就是这样做的.

但是,这并不能完全解决您的问题.我建议你从一个子类或装饰器类开始,如上面那个,然后显式添加支持-(NSArray*)allKeys,这NSDictionary本身就是一个标准访问器.然后,您可以添加支持以传递allKeys的更改消息,这将使其可观察.

这可以通过在-setObject:forKey:-removeObjectForKey:方法周围添加以下代码来完成.

- (void)setObject:(id)anObject forKey:(id)aKey
{
    BOOL addKey=NO;
    if (![dictionary objectForKey: aKey]) {
        addKey=YES;
        [self willChangeValueForKey: @"allKeys"];   
    }
    [dictionary setObject:anObject forKey:aKey];
    if (addKey)
        [self didChangeValueForKey: @"allKeys"];
}

- (void)removeObjectForKey:(id)aKey
{
    [self willChangeValueForKey: @"allKeys"];
    [dictionary removeObjectForKey:aKey];
    [self didChangeValueForKey: @"allKeys"];
}
Run Code Online (Sandbox Code Playgroud)

这里要做的是,当字典的键被更改为标记数组中的更改时,我们将向类添加显式KVO通知.

这将负责添加和删除.如果您希望以相同的方式通知更改,则可以删除if语句,只需在设置或删除时通知allKeys,如下所示:

- (void)setObject:(id)anObject forKey:(id)aKey
{
    [self willChangeValueForKey: @"allKeys"];   
    [dictionary setObject:anObject forKey:aKey];
    [self didChangeValueForKey: @"allKeys"];
}
Run Code Online (Sandbox Code Playgroud)

然后,在您的代码中,您为此对象上的键@"allKeys"放入一个观察者,并且您将在项目更改时接收通知.


Vin*_*nie 0

你不能子类化 NSMutableDictionary 并覆盖各种设置器吗?例如,通过调用 super 覆盖 setObject:forKey:,然后立即调用 addObserver...

您还可以为 NSMutableDictionary 编写一个包装器,在其中强制自己使用自定义设置器来操作底层 NSMutableDictionary。

也许我需要更多背景信息来了解您的任何限制或可扩展性意图。