Managing the Reordering of Rows

What Happens When a Row is Relocated
1. The delegate assigns the controls in tableView:cellForRowAtIndexPath: by setting the showsReorderControl property of UITableViewCell objects to YES.

When the table view receives the setEditing:animated: message, it resends the same message to the cell objects corresponding to its visible rows. After that, the sequence of messages is as follows:
- Every time the dragged row is over a destination, the table view sends tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath: to its delegate (if it implements the method). In this method the delegate may reject the current destination for the dragged row and specify an alternative one.
- The table view sends tableView:moveRowAtIndexPath:toIndexPath: to its data source (if it implements the method). In this method the data source updates the data-model array that is the source of items for the table view, moving the item to a different location in the array.
Examples of Moving a Row
Listing 8-1 Excluding a row from relocation
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) // Don't move the first row
return NO;
return YES;
}
Listing 8-2 Updating the data-model array for the relocated row
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
NSString *stringToMove = [[self.reorderingRows objectAtIndex:sourceIndexPath.row] retain];
[self.reorderingRows removeObjectAtIndex:sourceIndexPath.row];
[self.reorderingRows insertObject:stringToMove atIndex:destinationIndexPath.row];
[stringToMove release];
}
Listing 8-3 Retargeting the destination row of a move operation
- (NSIndexPath *)tableView:(UITableView *)tableView
targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
NSDictionary *section = [data objectAtIndex:sourceIndexPath.section];
NSUInteger sectionCount = [[section valueForKey:@"content"] count];
if (sourceIndexPath.section != proposedDestinationIndexPath.section) {
NSUInteger rowInSourceSection =
(sourceIndexPath.section > proposedDestinationIndexPath.section) ?
0 : sectionCount - 1;
return [NSIndexPath indexPathForRow:rowInSourceSection inSection:sourceIndexPath.section];
} else if (proposedDestinationIndexPath.row >= sectionCount) {
return [NSIndexPath indexPathForRow:sectionCount - 1 inSection:sourceIndexPath.section];
}
// Allow the proposed destination.
return proposedDestinationIndexPath;
}