samvermette
samvermette

Reputation: 40437

NSFetchedResultsController attempting to insert nil object?

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];
}

Upvotes: 4

Views: 2063

Answers (3)

Phil Viso
Phil Viso

Reputation: 643

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

Upvotes: 0

samvermette
samvermette

Reputation: 40437

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.

Upvotes: 3

Mundi
Mundi

Reputation: 80265

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.

Upvotes: 0

Related Questions