使用KVO与NSNotificationCenter观察对可变arrays的更改

在我的模型中,我有一个名为events的对象数组。 我想我的控制器被通知每当一个新的对象被添加到事件。

我认为这样做的好方法是使用KVO模式在事件发生变化时得到通知(从添加新对象开始)

// AppDelegate // events is a NSMutableArray @property/@synthesize etc... [appDelagate addObserver:self forKeyPath:@"events" options:NSKeyValueObservingOptionNew context:NULL]; 

但是, observeValueForKeyPath方法没有被调用,我发现数组不符合KVO 🙁

一种select是通过为keyPath调用willChangeValueForKey来手动触发该方法

 // ViewController [self willChangeValueForKey:@"events"]; [self.events addObject:event]; [self didChangeValueForKey:@"events"]; 

但是这样感觉很重,因为我应该跟踪事件数组的前后状态,以便可以通过observeValueForKeyPath方法来访问它。

一种方法是使用一个标准数组(而不是可变的),每次我想添加一个新的对象时创build/设置一个新的事件实例,或者我可以创build一个单独的属性来跟踪可变数组(我希望你可以观察@“events.count”)。

另一种select是使用NSNotificationCenter。 我也读过一些build议使用块的答案(但我不知道从哪里开始)。

最后,我是否可以在我的委托中保存我的控制器实例,并发送相关消息?

 // Delegate [myController eventsDidChange]; 

从代表保持对控制器的引用是否很奇怪?

我正在努力了解如何select哪个是最好的方法来使用,所以任何有关性能,未来的代码灵活性和最佳实践的build议,将不胜感激!

您不应该为可变集合制作直接的公共属性,以避免它们在您不知情的情况下发生变异。 NSArray本身不是关键值可观察的,但是你的一对多属性 @"events"是。 以下是如何观察它:

首先,申报一个不可改变的集合的公共财产:

 @interface Model @property (nonatomic, copy) NSArray *events; @end 

然后在你的实现中用一个可变的伊娃来回来:

 @interface Model () { NSMutableArray *_events; } @end 

并重写getter和setter:

 @implementation Model @synthesize events = _events; - (NSArray *)events { return [_events copy]; } - (void)setEvents:(NSArray *)events { if ([_events isEqualToArray:events] == NO) { _events = [events mutableCopy]; } } @end 

如果其他对象需要添加事件到你的模型,他们可以通过调用-[Model mutableArrayValueForKey:@"events"]来获得一个可变的代理对象。

 NSMutableArray *events = [modelInstance mutableArrayValueForKey:@"events"]; [events addObject:newEvent]; 

这将通过每次设置一个新的集合来触发KVO通知。 为了获得更好的性能和更精细的控制,请实现其余的数组访问器 。

另请参阅: 观察插入/移除的NSMutableArray 。

根据accessor方法的文档 ,你应该实现:

 - (void)addEventsObject:(Event*)e { [_events addObject:e]; } - (void)removeEventsObject:(Event*)e { [_events removeObject:e]; } 

然后KVO会在这些被调用时触发通知。