To change the order of rows in a UITableView, you will use another method from the UITableViewDataSource protocol – tableView:moveRowAtIndexPath:toIndexPath:.
To delete a row, you had to send the message deleteRowsAtIndexPaths:withRowAnimation: to the UITableView to confirm the deletion. Moving a row, however, does not require confirmation; the table view moves the row on its own authority and reports the move to its the data source by sending the message tableView:moveRowAtIndexPath:toIndexPath:. You just have to implement this method to update your data source to match the new order.
But before you can implement the data source method, you need to give the BNRItemStore a method to change the order of items in its allItems array. In BNRItemStore.h, declare this method.
- (void)moveItemAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex;
In BNRItemStore.m, implement moveItemAtIndex:toIndex:.
- (void)moveItemAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex { if (fromIndex == toIndex) { return; } // Get pointer to object being moved so you can re-insert it BNRItem *item = self.privateItems[fromIndex]; // Remove item from array [self.privateItems removeObjectAtIndex:fromIndex]; // Insert item in array at new location [self.privateItems insertObject:item atIndex:toIndex]; }
In BNRItemsViewController.m, implement tableView:moveRowAtIndexPath:toIndexPath: to update the store.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { [[BNRItemStore sharedStore] moveItemAtIndex:sourceIndexPath.row toIndex:destinationIndexPath.row]; }
Build and run your application. Check out the new reordering controls (the three horizontal lines) on the side of each row. Touch and hold a reordering control and move the row to a new position (Figure 9.9).
Note that simply implementing tableView:moveRowAtIndexPath:toIndexPath: caused the reordering controls to appear. The UITableView can ask its data source at runtime whether it implements tableView:moveRowAtIndexPath:toIndexPath:. If it does, the table view says, “Good, you can handle moving rows. I’ll add the re-ordering controls.” If not, it says, “If you aren’t implementing that method, then I won’t put controls there.”