NSFetchedResultsController is loading all rows even through I have batch set

After reading the docs on the NSFetchedResultsController initializer, I think the problem is that you have a sort in the fetch request (created) that doesn't naturally sort the same as the section key path (sectionIdentifier). The specific sentence in the docs I'm looking at says:

If this key path is not the same as that specified by the first sort descriptor in fetchRequest, they must generate the same relative orderings

I recommend modifying your fetch request to sort on sectionIdentifier first, then created. I think that'll fix your issue.

 NSSortDescriptor* updatedSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"created" ascending:NO];
 NSSortDescriptor* sectionSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"sectionIdentifier" ascending:NO];
 // It's critical the sectionSortDescriptor is first
 [fetchRequest setSortDescriptors:@[sectionSortDescriptor, updatedSortDescriptor]];

Note that if either the created or sectionIdentifier properties are actually methods on your entity class, that will definitely force Core Data to load all your data before it can sort/section, because it needs to execute that method on each entity first.


When using fetchBatchSize rather than returning the objects in an NSArray it returns a special batch faulting array. Although it does load in all the object IDs all the objects in the array are faults, meaning their data was not loaded, i.e. like a placeholder object. Then as you loop the array (or the table reload does) when access an object's property, it performs the database query for that object's properties including the next objects up to the fetchBatchSize (the minimum appears to be 4 by the way). The best way to debug this internal behaviour by seeing the queries is to edit your scheme and add a run argument:

-com.apple.CoreData.SQLDebug 1

That will output to console the various queries. You'll see the first query for the row IDs, then each batch loading of data.

So what you might be experiencing is it being slow to load in all the row IDs and creating the faulted objects, however that should be fast.

Another possibility is when it accesses the sectionIdentifier property to build the sections, that causes the object to be loaded in too, and thus causes all batches to load. To solve that you could try setting propertiesToFetch to include the sectionIdentifier, that way the first query should load in that property and then when it is accessed the object shouldn't be loaded in.