Observing Changes to a mutable array using KVO vs. NSNotificationCenter Observing Changes to a mutable array using KVO vs. NSNotificationCenter ios ios

Observing Changes to a mutable array using KVO vs. NSNotificationCenter


You should not make direct public properties for mutable collections to avoid them mutating without your knowledge. NSArray is not key-value observable itself, but your one-to-many property @"events" is. Here's how to observe it:

First, declare a public property for an immutable collection:

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

Then in your implementation back it with a mutable ivar:

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

and override the getter and setter:

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

If other objects need to add events to your model, they can obtain a mutable proxy object by calling -[Model mutableArrayValueForKey:@"events"].

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

This will trigger KVO notifications by setting the property with a new collection each time. For better performance and more granular control, implement the rest of the array accessors.

See also: Observing an NSMutableArray for insertion/removal.


Per the docs on accessor methods, you should implement:

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

Then KVO will fire the notifications when these are called.