views:

74

answers:

3

Hi all.

I have a UITableView that shows a list of objects stored with CoreData. I can delete an object using the following code:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
    NSLog(@"Delete row");
    [managedObjectContext deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]];

    // Save the context.
    NSError *error;
    if (![managedObjectContext save:&error]) {
        /*do this gracefully one day */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    [self refreshTables]; //where refreshTables just reloads the data the table is using and calls [self.tableView reloadData];
}

}

But it has no animation or aesthetic.

When I try to animate by replacing

[self refreshTables]; 

with

[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

I get the following error:

Assertion failure in -[UITableView _endCellAnimationsWithContext:], >/SourceCache/UIKit_Sim/UIKit-1261.5/UITableView.m:920 2010-10-30 16:46:35.717 MyApp[38226:207] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted).'

I've tried having the deleteRowsAtIndexPaths code in a variety of places in the commitEditingStyle code with no luck (for example before removing the object from the mOC) but I can't seem to get around this error.

I know Apple's iPhoneCoreDataRecipes example handles the problem by setting up a delegate for the FetchedResultsController to handle editing / deleting rows, but at this stage in development, if possible, I just want a simple solution for animating those deleted objects.

How can I animate the removal of a row, before/after I remove the object from my managedObjectContext?

EDIT: I've tried having deleteRowsAtIndexPaths before and after removing the item from the mOC, with the same error.

A: 
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
 {
        if (editingStyle == UITableViewCellEditingStyleDelete) {
            NSLog(@"Delete row");

    // Delete the row first
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

    //Then delete the object.
            [managedObjectContext deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]];

            // Save the context.
            NSError *error;
            if (![managedObjectContext save:&error]) {
                /*do this gracefully one day */
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }


    }
Manjunath
No, that doesn't work. I did try that before posting. Same error: Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1261.5/UITableView.m:92
glenstorey
A: 

Are you using a NSFetchedResultsController at all?
You get this error because the object is still in your tableview datasource.

Maybe at this stage in development you are using the simple solution and populate NSArrays with objects from a NSFetchRequest. Then it will be pointless to remove the object from the managed object context


are you using a cache for the NSFetchedResultsController? I just had another look in the documentation and found this:

A controller thus effectively has three modes of operation, determined by whether it has a delegate and whether the cache file name is set.

No tracking: the delegate is set to nil. The controller simply provides access to the data as it was when the fetch was executed.

Memory-only tracking: the delegate is non-nil and the file cache name is set to nil. The controller monitors objects in its result set and updates section and ordering information in response to relevant changes.

Full persistent tracking: the delegate and the file cache name are non-nil. The controller monitors objects in its result set and updates section and ordering information in response to relevant changes. The controller maintains a persistent cache of the results of its computation.

So the mode of the controller is "No tracking". Which means objects are not removed from the controller if they are removed from the managed object.
What means just reloads the data in the code of refreshTables? Try to do the same before removing rows.
Or add those 20 lines needed to get the delegate working.

fluchtpunkt
I am using NSFetchedResultsController and a core data source with no problems. The sans-animation code successfully removes the coredata object. It's only the animation that is causing trouble.
glenstorey
@glenstorey I guess I didn't read your question thoroughly the first time, see my edit.
fluchtpunkt