Reputation: 14553
I am trying to load items from CoreData
into a UITableView
. The initial way I did it was to simply grab all the objects from my BankInfo
entity, stuff them into an array, and then use the array to populate the UITableViewCells
:
- (NSMutableArray *) bankInfos
{
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"BankInfo" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error;
NSMutableArray *bankInfos = (NSMutableArray*)[context executeFetchRequest:fetchRequest error:&error];
return bankInfos;
}
I'd heard that NSFetchedResultsController
could improve performance / memory management so I tried it out (basically implemented it the way Ray Wenderlich tutorial recommended):
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"FailedBankInfo" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"details.closeDate" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext sectionNameKeyPath:nil
cacheName:@"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
What I'm finding after using instruments to profile the code is that the NSFetchedResultsController
is taking about twice as long to load the objects into the UITableView
as my initial method was. This line in particular:
BankInfo *bankInfo = [_fetchedResultsController objectAtIndexPath:indexPath];
is taking 292 ms whereas loading the entire array of BankInfos
is taking about 150 ms. Anyone know why this is?
Upvotes: 2
Views: 1140
Reputation: 14553
The problem I was having didn't have to do with CoreData performance, but had to do with the fact that I was accidentally saving / loading full size images as thumbnails in the tableview. Once I fixed this, the performance issues went away.
Upvotes: 3
Reputation: 9857
Well, we are talking about ms, it is still quite fast.
The fetched results controller is doing a query to sqllite for each cell. You can turn on sqllite debug in xcode: -com.apple.CoreData.SQLDebug 1
and see for yourself.
The NSArray is populated, stored, and fetched entirely in memory.
The choice between an array and fetched controller is not to be done by taking 'speed' into account.
Basically, if you have a small array of objects, immutable while on screen, then you can safely choose NSArray as table datasource.
Instead, if you have lot of objects or planning to have a growing numbers of objects, that also need to be refreshed often, NSFetchedResultsController is the preferred choice.
Upvotes: 1