The easy way is to use an NSArrayController and add an observer like so:
[friendsArrayController addObserver:self forKeyPath:@"arrangedObjects.name" options:0 context:nil];
The hard way is to observe a model’s collection property and add/remove observers when objects get added/removed from the collection like so:
[person addObserver:self forKeyPath:@"friends" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (object == person && [keyPath isEqualTo:@"friends"]) {
if ([[change valueForKey:NSKeyValueChangeKindKey] intValue] == NSKeyValueChangeInsertion) {
for (Friend *newFriend in [change valueForKey:NSKeyValueChangeNewKey]) {
if (![observedFriends containsObject:newFriend]) {
[newFriend addObserver:self forKeyPath:@"name" options:0 context:nil];
}
}
}
else if ([[change valueForKey:NSKeyValueChangeKindKey] intValue] == NSKeyValueChangeRemoval) {
for (Friend *oldFriend in [change valueForKey:NSKeyValueChangeOldKey]) {
if (![observedFriends containsObject:oldFriend]) {
[oldFriend removeObserver:self forKeyPath:@"name"];
}
}
}
else if ([[change valueForKey:NSKeyValueChangeKindKey] intValue] == NSKeyValueChangeReplacement) {
for (Friend *newFriend in [change valueForKey:NSKeyValueChangeNewKey]) {
if (![observedFriends containsObject:newFriend]) {
[newFriend addObserver:self forKeyPath:@"name" options:0 context:nil];
}
}
for (Friend *oldFriend in [change valueForKey:NSKeyValueChangeOldKey]) {
if (![observedFriends containsObject:oldFriend]) {
[oldFriend removeObserver:self forKeyPath:@"name"];
}
}
}
}
}