I have an object that implements the indexed accessor methods for a key called contents. In those accessors, I call willChange:valuesAtIndexes:forKey: and didChange:valuesAtIndexes:forKey: when I modify the underlying array.
Don't do that. KVO posts the notifications for you when you receive a message to one of those accessors.
I also have a custom view object that is bound to contents via an NSArrayController. In observeValueForKeyPath:ofObject:change:context: the only value in the change dictionary for the NSKeyValueChangeKindKey I ever see is NSKeyValueChangeSetting. When I'm adding objects to the array, I expect to see NSKeyValueChangeInsertion.
For one thing, why are you using KVO directly? Use bind:toObject:withKeyPath:options:
to bind the view's property to the array controller's arrangedObjects
(I assume) property, and implement array accessors (including indexed accessors, if you like) in the view.
For another, remember that arrangedObjects
is a derived property. The array controller will filter and sort its content array; the result is arrangedObjects
. You could argue that permuting the indexes from the original insertion into a new insertion would be a more accurate translation of the first change into the second, but setting the entire arrangedObjects
array was probably simpler to implement (something like [self _setArrangedObjects:[[newArray filteredArrayUsingPredicate:self.filterPredicate] sortedArrayUsingDescriptors:self.sortDescriptors]]
).
Does it really matter? Have you profiled and found that your app is slow with wholesale array replacement?
If so, you may need to bind the view directly to the array's content
property or to the original array on the underlying object, and suffer the loss of free filtering and sorting.