NSFetchedResultsController returns objects with zero indices

Details are in the comments.

The following code:

// Perform the fetch... NSError *error = nil; if (![[self fetchedResultsController] performFetch:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } // Confirm that objects were fetched by counting them... NSLog(@"Number of Objects = %i", [[fetchedResultsController fetchedObjects] count]); // Confirm that sections exist by counting them... NSLog(@"Numbers of Sections = %i", [[fetchedResultsController sections] count]); for (id section in [fetchedResultsController sections]) { // Count number of objects in each section // _The fact that this outputs 0 is the first sign of trouble_ NSLog(@"Number of Objects in Section = %i", [section numberOfObjects]); } for (Reminder *reminder in [fetchedResultsController fetchedObjects]) { // Confirm that the objects fetched are in fact real objects // by accessing their "textContent" property... NSLog(@"textContent=%@", reminder.textContent); // Show that the fetched objects are being returned // with a (null) indexPath... // _The second sign of trouble..._ NSLog(@"IndexPath=%@", [fetchedResultsController indexPathForObject:reminder]); } NSUInteger indexArr[] = {0,0}; NSIndexPath *indexPath = [NSIndexPath indexPathWithIndexes:indexArr length:2]; // _Application crashes on this line because the fetched // objects do not have indexPaths_ Reminder *testReminder = (Reminder *)[fetchedResultsController objectAtIndexPath:indexPath]; NSLog(@"textContent = %@", testReminder.textContent); 

Results in the next release:

 2010-07-17 00:48:41.865 Reminders[27335:207] Number of Objects = 3 2010-07-17 00:48:41.867 Reminders[27335:207] Numbers of Sections = 1 2010-07-17 00:48:41.868 Reminders[27335:207] Number of Objects in Section = 0 2010-07-17 00:48:41.870 Reminders[27335:207] textContent=Imported Object 3 2010-07-17 00:48:41.871 Reminders[27335:207] IndexPath=(null) 2010-07-17 00:48:41.873 Reminders[27335:207] textContent=Imported Object 2 2010-07-17 00:48:41.873 Reminders[27335:207] IndexPath=(null) 2010-07-17 00:48:41.874 Reminders[27335:207] textContent=Imported Object 1 2010-07-17 00:48:41.875 Reminders[27335:207] IndexPath=(null) 2010-07-17 00:48:41.887 Reminders[27335:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)' 

Any ideas would be highly appreciated. FYI, the above code works fine in a separate application if I use a different template as a starting point. That is, if I use the "Window-based application" template, the code will fail. If I use a “navigation-based application”, the code works as expected.

Update: TechZen wondered if the problem was caused by my Reminder entity. I thought it was a good idea to look, so I did the following:

  • Create two standard template applications: Application Window and Navigation Application (both with basic data enabled)

  • It is copied from the minimum code required from Nav-based for Window-based in order to perform the test described above (to a large extent, this is only the "xcdatamodel" file, the created control file and the way to add test objects).

The above code still does not work in the new reminder-essence window application. (In this new test application, in fact, there is zero code that I myself created (outside the test code), all this is just template code cut and pasted together.)

So now I'm looking for any way to get the above code to run after creating the "window application". Here is the code to run the test using the nav based entity in case someone is interested in trying:

UPDATE Please note that, as TechZen notes below, this code will be broken, no matter what, if you start with an empty database, therefore, if you start with a windowed application, first add several objects to the database, then add the test code.

 // Confirm that objects were fetched NSLog(@"Number of Objects = %i", [[fetchedResultsController fetchedObjects] count]); // Confirm that sections exist NSLog(@"Numbers of Sections = %i", [[fetchedResultsController sections] count]); for (id section in [fetchedResultsController sections]) { // Count number of objects in sections // _The fact that this outputs 0 is the first sign of trouble_ NSLog(@"Number of Objects in Section = %i", [section numberOfObjects]); } for (NSManagedObject *managedObject in [fetchedResultsController fetchedObjects]) { // Confirm that the objects fetched are in fact real objects, // by accessing their "timeStamp" property NSLog(@"TimeStamp=%@", [[managedObject valueForKey:@"timeStamp"] description]); // Show that the fetched objects are being returned // with a (null) indexPath // _The second sign of trouble..._ NSLog(@"IndexPath=%@", [fetchedResultsController indexPathForObject:managedObject]); } NSUInteger indexArr[] = {0,0}; NSIndexPath *indexPath = [NSIndexPath indexPathWithIndexes:indexArr length:2]; // _Application crashes on this line, because the fetched // objects do not have indexPaths_ NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath]; NSLog(@"textContent = %@", [[managedObject valueForKey:@"timeStamp"] description]); 

UPDATE Here is the result when using the new cut and paste code

 2010-07-18 15:33:41.264 Reminders[30898:207] Number of Objects = 3 2010-07-18 15:33:41.266 Reminders[30898:207] Numbers of Sections = 1 2010-07-18 15:33:41.267 Reminders[30898:207] Number of Objects in Section = 0 2010-07-18 15:33:41.270 Reminders[30898:207] TimeStamp=2010-07-18 13:59:00 -0400 2010-07-18 15:33:41.271 Reminders[30898:207] IndexPath=(null) 2010-07-18 15:33:41.272 Reminders[30898:207] TimeStamp=2010-07-18 13:59:00 -0400 2010-07-18 15:33:41.273 Reminders[30898:207] IndexPath=(null) 2010-07-18 15:33:41.274 Reminders[30898:207] TimeStamp=2010-07-18 13:58:59 -0400 2010-07-18 15:33:41.275 Reminders[30898:207] IndexPath=(null) 2010-07-18 15:33:41.276 Reminders[30898:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)' 

UPDATE . Therefore, I narrowed down this problem to a problem with the SDK version, I now have a project that, if I build with Simulator 3.2, it works and builds with Simulator 3.1.3, it works well. BUT, if I add a UITableViewController and then create using Simulator 3.2, then it works fine. So I created a message to https://stackoverflow.com/a/1366098/ ... to ask a question: if you use NSFetchedResultsController without a UITableViewController, how do you interact with objects? (since IndexPaths are unreliable).

UPDATE This problem is (tentatively) resolved by using - [NSFetchedResultsController fetchedObjects] objectAtIndex:] to access the objects.

+3
source share
6 answers

This can be circumvented with - [NSFetchedResultsController fetchedObjects] objectAtIndex:]

+3
source

I suppose I would be foolish to point out that NSLog (@ "% @", indexPath) always returns null?

You need to do

 NSLog(@"section %i",(int)indexPath.section); NSLog(@"row %i",(int)indexPath.row); 

Is not it?

+2
source

Have you tried using NSFetchedResultsController in memory only tracking mode? (Tracking only memory: the delegate is not zero, and the file cache name is set to zero)

+2
source

Take a look at the sortDescriptors fetchedResultsController order. The section key field must first sort the descriptor in order.

If the fetchedResultsController has several sortDescriptor descriptors, and the first descriptor is not a section section field than indexPathForObject: the method could not resolve indexPath.

+1
source

What does creating an NSFetchedResultsController look like?

Update

FYI, you can update your question with code instead of using PasteBin.

Do you use multiple threads in this code to access the NSFetchedResultsController ?

0
source

I copied and pasted your code into the default Core Data navigation template, changed the object to Reminder with the string attribute textContent , and it went fine. There is nothing wrong with this code or setting up the selected result controller.

I think the problem is actually related to your Reminder entity, Reminder class or attribute or textContent object. These errors can be caused by improper handling of reminder objects.


Edit:

Make sure that you run this test only after some objects have been added to the context. It will be broken if there are no objects. I will test using a window-based template.

0
source

Source: https://habr.com/ru/post/1316103/


All Articles