views:

71

answers:

2

Just run into a tricky NSFetchedResultsController problem.

The following code works fine in all cases EXCEPT for the very first entry to the Core Data database when it reports 2 rows!

id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
numberOfRows = [sectionInfo numberOfObjects];

If I add additional entries these are reported correctly. And if I delete both of the 2 initial rows it works fine.

Any suggestions? If it's any help, by using:

  -com.apple.CoreData.SQLDebug 1

I can see there was 1 INSERT and 2 SELECTs.

Also, this problem doesn't seem happen if I've already visited the view containing the NSFetchedResultsController code (i.e. before doing the INSERTs).

====
UPDATE 1:
Wonder if this walk through the code will help...
1. ViewController A starts a background NSOperation which does a download
2. When this completes it sends a notification to the AppDelegate
3. When the AppDelegate gets this notification it imports the data (doing a check to make sure it's on the main thread before doing so)

Here's the relevant bit of the importerDidSave code (where this technique was taken from):

- (void)importerDidSave:(NSNotification *)saveNotification {  
   NSLog(@"In importerDidSave...");  
   if ([NSThread isMainThread]) {  
     NSLog(@"... on Main Thread.");     
     NSLog(@"Number of NSFetchedResultsController rows BEFORE: %d", [[[fetchedResultsController sections] objectAtIndex:0] numberOfObjects]);  
     [self.managedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification];  
     NSLog(@"Number of NSFetchedResultsController rows AFTER: %d", [[[fetchedResultsController sections] objectAtIndex:0] numberOfObjects]);  

which outputs:

... on Main Thread.  
Number of NSFetchedResultsController rows BEFORE: 1  
Number of NSFetchedResultsController rows AFTER: 3
A: 

That code is correct. I would look at the way you are adding the data to the store.

Gordon Fontenot
Yes, the code is correct.However, the problem is not to do with adding the data to the store.Looking at the SQLite database I can see there is just 1 row (which agrees with the SQL debugging that mentions 1 INSERT).For some reason, NSFetchedResultsController is returning an incorrect number of rows (but only in the special case outlined above).
Snow Crash
A: 

Don't rely on direct SQL debugging. Core Data's use of SQL is so buried behind the objects (it doesn't even use SQL all the time) that you can't tell the state of the object graph by looking at the SQL.

Most likely, you have two objects in the section but one is in memory and one in the persistent store. Only the persisted object would be apparent in the SQL debug. You could have thousands of objects in the graph and thousands of rows in a table section but until the objects are persisted, they won't show in the SQL. Moreover, the pattern of SQL inserts and deletes will not directly reflect the insertions and deletes of the object graph.

In short, the SQL debug is pretty useless for debugging Core Data and you should ignore it in the vast majority of cases.

If the fetched results controller reports two objects in the section then there are two objects in the section. Where the extra object came from, I can't say without more information.

Check:

  1. Your section key if any. If your sections are misconfigured you will have rows where you don't expect them.
  2. Check your insertion to see if you are duplicating insertions.

You can confirm whether FRC is correct by manually performing the same fetch it uses yourself and seeing what gets returned. Sort the return on each section key and you can see how many objects appear in the section.

TechZen