Search code examples
ioskey-value-observingkvc

KVO on removeAllObjects Triggers NSKeyValueChangeRemoval for each Item Separately


I'm watching an NSArray property with KVO. I've implemented KVC like in this post and I also implemented most of the KVC array accessors. To mutate it, I use mutableArrayValueForKey. It works fine, except to 2 issues:

  1. When I call removeAllObjects, I get a NSKeyValueChangeRemoval change for each single removed item. I'd like to receive only one NSKeyValueChangeRemoval notification with all removed indexes in it.

  2. Similarly when I call addObjectsFromArray:, I get NSKeyValueChangeInsertion for each single added item. I'd like to receive only one NSKeyValueChangeInsertion notification with all added indexes in it.


Notice that I do have implemented the KVC methods remove<Key>ItemsAtIndexes: and insert<Key>Items:atIndexes:. They are not called though.

I use the following workarounds:

- (void)removeAllObjectsWorkaroundFromArray:(NSMutableArray *)modelArray {
    NSRange indexRange;
    indexRange.length = modelArray.count;
    indexRange.location = 0;
    NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:indexRange];
    [modelArray removeObjectsAtIndexes:indexSet];
}

- (void)addObjectsFromArrayWorkaroundWithArray:(NSMutableArray *)modelArray arrayToAdd:(NSArray *)arrayToAdd {
    NSRange indexRange;
    indexRange.length = arrayToAdd.count;
    indexRange.location = modelArray.count;
    NSIndexSet *indexSet = [[NSIndexSet alloc] initWithIndexesInRange:indexRange];
    [modelArray insertObjects:arrayToAdd atIndexes:indexSet];
}

Is there a way to directly use removeAllObjects and addObjectsFromArray: without the need for the above workarounds?


Solution

  • As I am sure you are aware one cannot observe the array itself, just attributes of it. So I think your workaround is unavoidable.

    That being said - I really like the way you solved this!