Core Data and UITableView – Re-ordering Rows Magic

This is as much for my reference as it is for yours. I have a situation where I needed to re-order rows in a UITableView. The models in table view are part of a Core Data to-many relationship, so I have an attribute on the model called position.

Full disclosure: I am basically re-hashing this post on stack overflow.

This is basically what was causing me problems: “NSFetchedResultsController and its delegate are not meant to be used for user-driven model changes.” and I was trying to re-assign position values, which would in turn update the managedObjectContext, which would in turn update the NSFetchedResultsController and there would be a lot of mayhem and incorrectly set data.

To make this brief, basically on any UITableViewController, or any UIViewController that implements UITableViewDataSource and UITableViewDelegate along with NSFetchedResultsControllerDelegate, add a private property called:

@property (nonatomic, assign, getter=isManuallyReordering) BOOL manuallyReordering;

and use it in your delegate methods as such:

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
 self.manuallyReordering = YES;

 //...[UPDATE THE MODEL then SAVE CONTEXT]...

 self.manuallyReordering = NO;
}

and in this time ignore change messages sent to the NSFetchedResultsControllerDelegate

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
 if (self.isManuallyReordering) return;
 //...
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
 if (self.isManuallyReordering) return;
 //...
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
 if (self.isManuallyReordering) return;
 //...
}

There it is.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s