1

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?

Didier Ghys
  • 30,396
  • 9
  • 75
  • 81
user266429
  • 31
  • 1
  • 4

1 Answers1

2

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.

Jim
  • 5,940
  • 9
  • 44
  • 91
  • Thanks for your reply - I definitely need to do some more homework on this issue - I'll start with your reference. The delegate methods you list are in my program but are not currently being called, so I felt there must be something amiss. I thought I had implemented the protocol but something is off. I'll give it some more thought and research. – user266429 Jan 12 '12 at 00:02
  • There's actually a good example in the Apple projects - CoreData Books - It does pretty much what I want - BUT it doesn't use a storyboard. So I'm trying to do the translation to the new environment. – user266429 Jan 12 '12 at 00:07
  • Make sure you set the fetchedResultsController's delegate to the controller that has the delegate methods in it. – Jim Jan 12 '12 at 00:56
  • Jim - you nailed it - thanks! I did declare the delegate - but before I actually allocated the fetchedResultsController. DOH! But your hint showed me my stupid mistake. I'll buy ya a drink someday. – user266429 Jan 12 '12 at 04:02