9

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.

elementsense
  • 1,540
  • 3
  • 15
  • 21

3 Answers3

15

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.

elementsense
  • 1,540
  • 3
  • 15
  • 21
  • 3
    I spoke with an Apple engineer at WWDC about this. He said that this was a bug in UITableView (that has been fixed in 4.0). If you are on < 4.0, just call `reloadData` like that. If you are on >= 4.0, do it like the documentation says. – Sam Soffes Aug 30 '10 at 19:05
  • 1
    You sir, just solved a problem that was bleeding into it's 6th hour. If I could upvote twice, I would. – Cyprus106 May 01 '14 at 01:52
2

Adopting the fix by Apple in iPhoneCoreDataRecipes in version 1.2, the proper thing to do is to replace

 // Reloading the section inserts a new row and ensures that titles are updated appropriately.
 [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];

with

    [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];

(FileMerge is your friend!)

Note, there's another fix in version 1.2 that prevents erratic crashing when creating new entries. I had reported this and it was fixed within two weeks. I encourage you to file bug reports with Apple. They're far more responsive than you think, and you can expect to get the best possible fix.

sra
  • 23,820
  • 7
  • 55
  • 89
oliverue
  • 21
  • 1
0

You need to implement the controller:didChangeSection:atIndex:forChangeType: delegate methods. In it, send insertSections:withRowAnimation:, deleteSections:withRowAnimation:, and reloadSections:withRowAnimation: messages to your table view depending on the reported change type.

Ole Begemann
  • 135,006
  • 31
  • 278
  • 256