Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Batching Core Data fetch results

I'm executing a fetch request that returns about 2000 entities. Currently, this takes about 20 seconds on my device. So I thought I might set a fetch limit of 100, and then when the user scrolls to the end of the table view, fetch the next 100 entities. This can be accomplished using NSFetchRequest's setFetchLimit and setFetchOffset.

However, what I can't figure out is, if on my second fetch where I'm fetching objects 101-200, what would happen to the objects 1-100? Would I have to use separate NSFetchedResultsController for every 100 items, and then configure my table view data source methods to query based on multiple fetch results controllers? Or can I somehow use the same NSFetchedResultsController to somehow fetch 100 entities at a time, but upon every subsequent fetch, just add the next 100 items to the original 100 items?

Edit: Here's my code:

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription 
                                   entityForName:@"MessageObject" inManagedObjectContext:appDelegate.managedObjectContext];

    [fetchRequest setEntity:entity];
    NSPredicate *predicate= [NSPredicate predicateWithFormat:@"ANY tags.tagName==%@", currentTagObject.tagName];
    [fetchRequest setPredicate:predicate];
    NSSortDescriptor *sort= [[NSSortDescriptor alloc] initWithKey:@"createDate" ascending:NO selector:@selector(compare:)];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
    [fetchRequest setFetchBatchSize:5];
like image 207
Snowman Avatar asked Jun 22 '12 23:06

Snowman


2 Answers

You don't actually need to do anything to achieve the fetching in batches of the size you've specified. You will get the behavior you're describing simply be executing a single fetch request on a single controller - by setting the batch size property, you're simply hinting to CoreData what you consider to be the optimal batch size by your own consideration. CoreData will handle fetching objects in sequential batches of the size specified as you need them - and it will fault managed objects when necessary for memory consumption.

like image 98
isaac Avatar answered Nov 13 '22 14:11

isaac


Using ANY is a pretty expensive operation. I'm not sure about the relationships, but you Could try fetching your tags entity for the specific tag name rather than on your mesage object entity. Then use the inverse relationship to get the message object entities

Also your sort is using a comparator which I'm sure is not helping matters. The date should be stored by core data as an integer number so you can just do a straight sort without using a selector.

Core Data is VERY fast, I've done a keyword search through 65,000 records and have had returned results in milliseconds.

Good luc

like image 21
timthetoolman Avatar answered Nov 13 '22 15:11

timthetoolman