Last Updated: February 25, 2016
·
1.995K
· bontojr

NSArray category for moving objects in a UITableView

Most newcomers of Objective-C and iOS development use to make a big mistake when dealing for the first time with a UITableView and the delegate to move items (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath.

I've seen a lot of times this:

// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
    [self.items exchangeObjectAtIndex:toIndexPath.row withObjectAtIndex:fromIndexPath.row];
}

This is absolutely wrong!
It works if you're moving adjacent objects, but not if you're moving an object from index 1 to index 7, for example.

For this, there's a nice category, the biggest 'missing method' in NSArray:

//NSMutableArray+Additions.h
@interface NSMutableArray (Additions)

- (void)moveObjectFromIndex:(NSUInteger)from toIndex:(NSUInteger)to
@end

...

//NSMutableArray+Additions.m
@implementation NSMutableArray (Additions)

- (void)moveObjectFromIndex:(NSUInteger)from toIndex:(NSUInteger)to
{
    if (to != from) {
        id obj = [self objectAtIndex:from];
        [self removeObjectAtIndex:from];
        if (to >= [self count]) {
            [self addObject:obj];
        } else {
            [self insertObject:obj atIndex:to];
        }
    }
}

@end

Now you can simply do the following:

// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
    [self.items moveObjectFromIndex:fromIndexPath.row toIndex:toIndexPath.row];
}

That's it! Simple, isn't it?