Search code examples
objective-ccocoa-touchkey-value-observing

How should I handle the NSIndexSet from kvo to update a table view?


I am starting out using key value observing, and the mutable array I'm observing gives me NSIndexSets (Ordered mutable to-many) in the change dictionary. The problem is the table view as far as I know wants me to give it NSArrays full of indexes.

I thought about implementing a custom method to translate one to the other, but this seems slow and I get the impression there must be a better way to make this table view update when the array changes.

This is the method from my UITableViewDataSource.

 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
     switch ([[change valueForKey:NSKeyValueChangeKindKey] unsignedIntValue]) {
         case NSKeyValueChangeSetting:
             NSLog(@"Setting Change");
             break;
         case NSKeyValueChangeInsertion:
             NSLog(@"Insertion Change");

             // How do I fit this:
             NSIndexSet * indexes = [change objectForKey:NSKeyValueChangeIndexesKey];

             // into this:
             [self.tableView insertRowsAtIndexPaths:<#(NSArray *)#> withRowAnimation:<#(UITableViewRowAnimation)#>

             // Or am I just doing it wrong?

             break;
         case NSKeyValueChangeRemoval:
             NSLog(@"Removal Change");
             break;
         case NSKeyValueChangeReplacement:
             NSLog(@"Replacement Change");
             break;
         default:
             break;
     }
 }

Solution

  • This seems easy enough. Enumerate the index set using enumerateIndexesUsingBlock: and stick each index into an NSIndexPath object:

    NSMutableArray * paths = [NSMutableArray array];
    [indexes enumerateIndexesUsingBlock:^(NSUInteger index, BOOL *stop) {
            [paths addObject:[NSIndexPath indexPathWithIndex:index]];
        }];
    [self.tableView insertRowsAtIndexPaths:paths
                          withRowAnimation:<#(UITableViewRowAnimation)#>];
    

    If your table view has sections, it's only a bit more complicated, because you'll need to get the correct section number, and specify it in the index path:

    NSUInteger sectionAndRow[2] = {sectionNumber, index};
    [NSIndexPath indexPathWithIndexes:sectionAndRow
                               length:2];