18

I get the following error when trying to add a record:

Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. The index 0 is invalid with userInfo (null)

And that's it. I put breakpoints into all the fetchedResultsContainer delegate methods I have implemented, but nothing breaks.

I tracked it down to:

  NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"titleFirstLetter" cacheName:@"Root"];

"sectionNameKeyPath" is the problem. "titleFirstLetter" is a transient property that I created a getter for in my NSManagedObject subclass.

Here's the getter:

-(NSString *)titleFirstLetter
{
  [self willAccessValueForKey:@"titleFirstLetter"];
  NSString *aString = [[self valueForKey:@"title"] uppercaseString];

  NSString *stringToReturn = [aString substringWithRange:[aString rangeOfComposedCharacterSequenceAtIndex:0]];

  [self didAccessValueForKey:@"titleFirstLetter"];
  return stringToReturn;
}

When I change the sectionNameKeyPath to nil, it works, but is obviously not what I want. It also works when I have a title already filled in for my model, so that titleFirstLetter doesn't return nil, though that doesn't seem to be quite the problem. If I make the string something arbitrary if it's nil, it still crashes.

Any idea what's up here?

UPDATE: If I use the title in the sectionNameKeyPath instead of the transient property, it doesn't crash, but obviously puts every item in its own section. So it's somehow related to the transient property...

UPDATE2: Some preliminary hacking with using a persistent property instead of transient, and no other changes, seems to work just fine, so this looks to be a bug. I have a bug report open: #8553064

UPDATE3: Well, scratch that. Using a persistent attribute didn't make any difference. I am somewhat at whits end now.

Thanks!

Christoph
  • 1,580
  • 5
  • 17
  • 29

5 Answers5

12

Well, this is probably partly (or fully) user error. The problem was that, in the view in which I add a new item, I had put [self.tableView reloadData] inside the viewWillAppear method. Commenting that out did not updated the table cells, but prevented the crash.

I then went ahead and sent reloadRowsAtIndexPaths:withRowAnimation: to the table view to manually reload the few cells that needed it.

I am glad that's finally over!

coder
  • 10,460
  • 17
  • 72
  • 125
Christoph
  • 1,580
  • 5
  • 17
  • 29
2

I thought this was my issue. I had got the same warning message, but my solution was VERY different.

You can get this error if you haven't properly implemented all of the NSFetchedResultsController Delegate methods. I always just copy and paste the 4 methods from Apple for how to implement NSFetchedResultsController.

Unfortunately I had missed one of these :

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView beginUpdates];
}

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

MAKE SURE YOU'VE GOT EM, else you'll pull out your hair like me.

hatunike
  • 1,967
  • 1
  • 19
  • 26
  • This is a very simple solution to a common problem. While all the other answers I'm sure are also right, this subtle mistake can also generate the same error. Worth noting. – M. Ryan Aug 10 '17 at 04:12
2

The default behavior of the fetched results controller is to create one section for each first letter of the sectionNameKeyPath. You shouldn't be getting one section per item unless every item starts with a different letter.

If you want to customize the section name behavior, subclass NSFetchedResultsController and override sectionIndexTitleForSectionName: and sectionIndexTitles. See the NSFetchedResultsController docs for details.

TechZen
  • 64,370
  • 15
  • 118
  • 145
  • Then what am I doing wrong here? http://assets.zerodeviation.net/sections.png This is with the title as the sectionNameKeyPath. – Christoph Oct 15 '10 at 22:09
  • To add to this, the docs say that the __IndexTitle__ is by default the capital first letter. And that's true. But I am talking about the section titles. – Christoph Oct 15 '10 at 22:24
  • The indexTitles are the section titles. Look at how the contact app list names. It uses this exact built in method. I don't know why your getting this problem. Most likely you have somewhere crossed up the attributes. – TechZen Oct 17 '10 at 18:40
  • Not really. I want them to be the same, but they aren't if I do it that way. As the docs say, index titles are first letter capitalized by default, section titles are not necessarily. – Christoph Oct 22 '10 at 04:00
1

I discovered another way to arrive at this same cryptic exception. My transient property - like yours, to extract the first letter - wasn't guarded against a 0-length string (@""). The attempt to get its first character threw an exception and resulted in this Core Data error (and not the exception you would expect to see).

Evan Schoenberg
  • 943
  • 8
  • 7
0

Important

NSFetchedResultsController * consultMessageFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[[[WYCoreDataStorage shareStore] coreDataHelper] mainContext] sectionNameKeyPath:nil cacheName:nil];

If you are using a cache, you must call deleteCacheWithName: before changing any of the fetch request, its predicate, or its sort descriptors. You must not reuse the same fetched results controller for multiple queries unless you set the cacheName to nil.

Jay Bhalani
  • 4,142
  • 8
  • 37
  • 50
wujuan
  • 1