Animated Sorting in UITableView

No Comments

Let me share another rather simple but neat trick which is quite useful when you need to sort a list of items visually represented by UITableView. Let’s say we have an NSArray holding a list of cities stored in arbitrary order. And in your app you’d like to offer an option to sort the list in one or the other way.

Sorting as such is very easy to implement since NSArray class already offers a number of methods (sortedArrayUsing…) which allow you to get the sorted version of the array by passing one of the following: NSSortDescriptor, comparator block, sorting C function or selector of the sorting method. To update the table view, you would then probably call [self.tableView reloadData].

That works just fine but wouldn’t it be better to provide nice animated feedback to user by moving table view cells into right slots? This is almost just as easy. The key to the solution is to use batch update mechanism built right into UITableView allowing to apply multiple changes all at once. The animation of the table view cells would be then achieved by already available [UITableView moveRotAtIndexPath:toIndexPath:]. We just need to calculate source and destination index paths for each cell which needs to be moved since the underlying data element changed it’s position during sorting operation.

Let’s have a look at the code:

- (IBAction)sort {
 
    // We need an unsorted copy of the array for the animation
    NSArray *unsortedList = [self.cities copy];
 
    // Sort the elements and replace the array used by the data source with the sorted ones
    self.cities = [self.cities sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        return [obj1 compare:obj2];
    }];
 
    // Prepare table for the animations batch
    [self.tableView beginUpdates];
 
    // Move the cells around
    NSInteger sourceRow = 0;
    for (NSString *city in unsortedList) {
        NSInteger destRow = [self.cities indexOfObject:city];
 
        if (destRow != sourceRow) {
            // Move the rows within the table view
            NSIndexPath *sourceIndexPath = [NSIndexPath indexPathForItem:sourceRow inSection:0];
            NSIndexPath *destIndexPath = [NSIndexPath indexPathForItem:destRow inSection:0];
            [self.tableView moveRowAtIndexPath:sourceIndexPath toIndexPath:destIndexPath];
 
        }
        sourceRow++;
    }
 
    // Commit animations
    [self.tableView endUpdates];
}

I hope you enjoyed this example. You can download the full sample project here: AnimatedTableSorting. Take care!