How to refresh a UITableViewController or NSFetchedResultsController?

elementsense picture elementsense · Jun 19, 2010 · Viewed 17.1k times · Source

I have a little problem with my UITableViewController or NSFetchedResultsController. I am not sure which is the problem soure but I guess its the UITableViewController.

As I said I use a NSFetchedResultsController to fill my data into a UITableViewController. The data is sorted by date and is also displayed in sections by date-year, e.g. May 2010/June 2010/ and so on. This is displayed as the section header.

Now when I add new data, it automatically uses the current date as default, but if I want to use a date, that is currently not in the section list, e.g. April 2010 (currently May and June in the list), then this is not displayed correctly. Only when I quit the app and start it again it will show the new section headers and everything is fine.

So I somehow need to be able to refresh my list or update it. By just adding it to the context and changing it does not seem to update it.

Again, I am not sure what I need to update, if it is my NSFetchedResultsController object or the UITableViewController.

UPDATE #1:

I just figured that there is an exception in this method :

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{
    // The fetch controller has sent all current change notifications, so tell the table view to process all updates.
    [self.tableView endUpdates];

}

This is where I move the data :

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath 
{

    UITableView *tableView = self.tableView;

    switch(type) 
    {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
        //  [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];

            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            // Reloading the section inserts a new row and ensures that titles are updated appropriately.
            [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }

}

This method is pretty much taken from the CoreDataBooks example from Apple. And this is the error :

Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. *** -[NSMutableArray removeObjectAtIndex:]: index 1 beyond bounds [0 .. 0] with userInfo (null)

And after that, the edit mode (where the delete button appears) does not work anymore.

Thanks.

Answer

elementsense picture elementsense · Jun 20, 2010

Ok, looks like I found a solution, I just skip these

[self.tableView beginUpdates];
[self.tableView endUpdates];

and always do this.

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{

[self.tableView reloadData];

}

I will obviously give this some more logic, since the problem only occures when I want to move my data in a section that does not exist before. Until someone can give me a real solution, I will go with this one.