类具有NSMutableArray类型的属性(和实例var),具有合成访问器(via @property
).如果使用以下方法观察此数组:
[myObj addObserver:self forKeyPath:@"theArray" options:0 context:NULL];
然后在数组中插入一个对象,如下所示:
[myObj.theArray addObject:NSString.string];
不发送observeValueForKeyPath ...通知.但是,以下内容确实发送了正确的通知:
[[myObj mutableArrayValueForKey:@"theArray"] addObject:NSString.string];
这是因为mutableArrayValueForKey
返回一个负责通知观察者的代理对象.
但是,合成访问器不应该自动返回这样的代理对象吗?解决这个问题的正确方法是什么 - 我应该编写一个只调用的自定义访问器[super mutableArrayValueForKey...]
吗?
但是,合成访问器不应该自动返回这样的代理对象吗?
没有.
解决这个问题的正确方法是什么 - 我应该编写一个只调用的自定义访问器
[super mutableArrayValueForKey...]
吗?
不.实现数组访问器.当您拨打这些电话时,KVO会自动发布相应的通知.所以你要做的就是:
[myObject insertObject:newObject inTheArrayAtIndex:[myObject countOfTheArray]];
正确的事情将自动发生.
为方便起见,您可以编写一个addTheArrayObject:
存取器.这个访问器将调用上述真正的数组访问器之一:
- (void) addTheArrayObject:(NSObject *) newObject { [self insertObject:newObject inTheArrayAtIndex:[self countOfTheArray]]; }
(您可以而且应该为数组中的对象填写适当的类,而不是NSObject
.)
然后,而不是[myObject insertObject:…]
,你写[myObject addTheArrayObject:newObject]
.
遗憾的是,add
它的对应remove
物,我最后检查过,只能被KVO识别为set(如在NSSet中)属性,而不是数组属性,所以除非你在它确实识别的访问器之上实现它们,否则你不会得到它们的免费KVO通知.我提交了一个关于此的错误:x-radar:// problem/6407437
我在我的博客上列出了所有访问者选择器格式.
我不会用willChangeValueForKey
,并didChangeValueForKey
在这种情况下.首先,它们意味着指示该路径上的值已经改变,而不是多对多关系中的值正在改变.willChange:valuesAtIndexes:forKey:
如果你这样做,你会想要使用它.即便如此,使用像这样的手动KVO通知也是不好的封装.更好的方法addSomeObject:
是在类中定义实际拥有该数组的方法,其中包括手动KVO通知.这样,将对象添加到数组的外部方法也不需要担心处理数组所有者的KVO,这不会非常直观,如果您开始向对象添加对象,可能会导致不需要的代码和可能的错误来自几个地方的阵列.
在这个例子中,我实际上会继续使用mutableArrayValueForKey:
.我对可变数组不是很肯定,但是我从阅读文档中相信这个方法实际上用一个新对象替换整个数组,所以如果性能是一个问题,你也需要实现insertObject:in
并且removeObjectFrom
在拥有数组的类中.
当您只想观察更改的计数时,您可以使用聚合键路径:
[myObj addObserver:self forKeyPath:@"theArray.@count" options:0 context:NULL];
但请注意,在阵列中的任何重新排序都不会触发.