4

For a long time I've been getting a strange bug where most of my table view becomes black (only a few cells remain http://cl.ly/LFlS) and in other views (connected to the same MOC) some other visual glitches appear: http://cl.ly/LH3c (notice the duplicate section headers). I always figured it was a bug with CoreData but I never got to reproduce it until today while it was hooked to the debugger. Here's the exception I got right before it happened:

CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. * -[__NSArrayM insertObject:atIndex:]: object cannot be nil with userInfo (null)

It stopped on the [tableView endUpdates] line in my controllerDidChangeContent: method. Then if I click continue, the app doesn't crash, but user interaction becomes extremely sluggish. I looked all over the place as of what might be the cause of that exception and couldn't find anything. Any clue?

My NSFetchedResultsController change handling looks pretty much like Apple's boilerplate. The init of my NSFRC looks like this:

NSFetchRequest *request = [[NSFetchRequest alloc] init];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Artist" inManagedObjectContext:[SWDataManager sharedManager].mainObjectContext];
[request setEntity:entity];

[request setFetchBatchSize:100];

NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"sortName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
[request setSortDescriptors:@[sortByName]];

fetchedResultsController = [[NSFetchedResultsController alloc]
                            initWithFetchRequest:request
                            managedObjectContext:mainObjectContext
                            sectionNameKeyPath:@"firstLetter"
                            cacheName:nil];

fetchedResultsController.delegate = self;
[self refreshDataSource]; // set fetch request predicate and call performFetch on NSFRC
return fetchedResultsController;

EDIT: I can add that this definitely happened after that a bunch of objects got deleted from my MOC and therefore from the table view.

As requested, my controllerDidChangeContent: code:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];

    // this updates the section index and footer cell and other kind of stuff
    [self performSelector:@selector(layoutSpecialCells) withObject:nil afterDelay:0.3];
}
samvermette
  • 40,269
  • 27
  • 112
  • 144
  • You will need to post your `-controllerDidChangeContent:`. – Mundi Nov 29 '12 at 13:57
  • @Mundi added. Like I said, it's nothing special... – samvermette Nov 29 '12 at 22:53
  • Also added screenshots of how my table views look after I get the exception. – samvermette Nov 29 '12 at 23:35
  • FYI, I was experiencing the same problem, and [this](http://stackoverflow.com/questions/19462645/nsfetchedresultscontroller-attempting-to-insert-nil-object) answer solved my issue. In my case, it seems that using ``NSFetchedResultsController`` with ``estimatedRowHeight`` when adding more cells to a table view, results in an uncaught exception that makes the table view unresponsive, laggy and not displayed correctly. – amb Apr 15 '14 at 07:47

3 Answers3

3

I ended up requesting a TSI with Apple and here's the gist of the answer I got:

To protect the integrity of the datastore, Core Data catches some exceptions that happen during it's operations. Sometimes this means that if Core Data calls your code through a delegate method, Core Data may end up catching exceptions your code threw.

In this case, Core Data caught an exception through from your -controllerDidChangeContent: method, caused by trying to use -insertObject:atIndex to put nil into an NSMutableArray.

So basically that exception is thrown by my code, and not necessarily by the Core Data framework. I still couldn't find the root cause of the exception, so the advice:

Multi-threading errors are the most common cause of mysterious Core Data issues.

went a long way and I realized some of my Core Data code wasn't encapsulated inside performBlock: calls. Once I got that fixed, I never saw the issue happen again.

samvermette
  • 40,269
  • 27
  • 112
  • 144
  • I have the same problem than you, with swift and xcode 6.3 and `performBlock` didn't solve my problem but removing `estimatedHeightForRowAtIndexPath` seems to work but it's just covering the bug not fixing it... – Nico Apr 13 '15 at 09:16
0

Why do you update the UI after [tableView endUpdates];? Why do you do it on a separate selector with a delay?

This seems to me very questionable design and likely the reason for your problems. I strongly recommend you do all the UI updates generated by the NSFetchedResultsControllerDelegate in the designated methods.

Mundi
  • 79,884
  • 17
  • 117
  • 140
  • Agreed that this is bad design. But like I said, that method doesn't alter the tableView's content at all. The method is quite lengthy so I won't bother posting it here but basically it: 1) toggles a UILabel on top of the table view; 2) sets up the table view's footer cell; 3) change the table view's contentInset and 4) toggles the vertical scroll indicator. I'll try disabling it but I'm not sure how those things could create that bug... – samvermette Dec 01 '12 at 00:12
  • Maybe there is a misunderstanding. The FRC delegate method responds to changes in the underlying data, not the table view. You should be looking for lines of code that modify your object graph. – Mundi Dec 01 '12 at 10:22
0

we may not have the exact same problem, but the errors you described were the same as mine. I'm using some newer APIs that didn't exist when you saw this, but I think I fixed my problem. Checkout update 5 if you're curious. NSFetchedResultsController attempting to insert nil object

Community
  • 1
  • 1
Phil Viso
  • 643
  • 7
  • 11