UITableView NSFetchedResultsController philosophy

505 Views Asked by At

I am displaying data from CoreData in a UITableView using NSFetchedResultsController as the container for the NSManagedObjects. The code for deleting a row works well, but my implementation strikes me as less than elegant. Is there a better way?

The code below illustrates the deletion event:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

{
    if (editingStyle == UITableViewCellEditingStyleDelete) {

        // Delete the row from the data source 
       [myContext deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]];

        if (![myContext save:&error]) { 
            // Error handling
        }  

        fetchedResultsController = nil;

        if (![[self getFetchedResultController] performFetch:&error]) {
             // Error handling
        }
        [tableView reloadData];        
    }   
}

I set the fetchedResultsController to nil and perform another fetch to update the new contents.

What concerns me is that I have seen references on various forums hinting that a change in the context should automatically engender changes in the fetchedResultsController and perhaps this second fetch is unnecessary. I have not implemented sections at this point.

Another concern is that the code simply makes the row disappear without any animation.

Could some slick animation be introduced?

1

There are 1 best solutions below

4
On

Look into using the NSFetchedResultsControllerDelegate Protocol methods to manage changes to the table and the database. This way, whenever you do a save within the NSManagedObjectContext of the NSFetchedResultsController, that fetchedResultsController will be notified by the managed ojbect context. Then the fetchedResultsCotnroller will call its delegate methods.

You want to implement controllerWillChangeContent: and controllerDidChangeContent: so you can bracket the calls of the other delegate methods with calls to the beginUpdates and endUpdates methods for the table view. (See the example in the reference.) This keeps the table view from getting out of synchronization with the fetchedResultsController.

Then delete these line:

 fetchedResultsController = nil;

        if (![[self getFetchedResultController] performFetch:&error]) {
             // Error handling
        }
        [tableView reloadData];     

Once you have done this, you can introduce animations in the insertion and deletion of cells.