Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data: Background fetch, NSFetchedResultsController and Sorting time

the problem I am encountering is the following:

I have a UITableView which I feed with data from an NSFetchedResultsController which retrieves around 6000 rows from core data. The fetchBatchSize of the NSFetchRequest is set to 20 and if I do not apply any NSSortDescriptor the fetch is fast enough to not block the UI thread.

However, I do need to display those rows sorted alphabetically for which I use the following NSSortDescriptor:

[[[NSSortDescriptor alloc] initWithKey:@"optionText" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)] autorelease];

And here is when things change, the fetch operation now takes around 3 seconds to complete because the 6000 rows are being sorted. Obviously during those seconds the UI is blocked and the user experience is terrible.

I know that I could do the fetch in a background thread and then pass to object IDs to the main thread, but in that case how could I still use the NSFetchedResultsController in the main thread (I am also using it to observe changes on the data)?

I have also indexed the attribute on which I am sorting but that only optimises look-ups and not sorting performance.

Any ideas would be much appreciated, thanks!

like image 603
monchote Avatar asked Apr 14 '11 09:04

monchote


2 Answers

How about using NSFetchRequest's batchSize property?

If you set a non-zero batch size, the collection of objects returned when the fetch is executed is broken into batches. When the fetch is executed, the entire request is evaluated and the identities of all matching objects recorded, but no more than batchSize objects’ data will be fetched from the persistent store at a time. The array returned from executing the request will be a proxy object that transparently faults batches on demand. (In database terms, this is an in-memory cursor.)

like image 159
samvermette Avatar answered Sep 27 '22 20:09

samvermette


I do a background batch imports in an NSOperation which uses a separate NSManagedObjectContext. Periodically I save the second context, which fires a notification to update my main NSManagedContext which my NSFetchedResultsController is hooked up to.

Maybe a similar technique could be applied to your fetch

Here is a cocoa is my girlfriend article about it:

http://www.cimgf.com/2011/05/04/core-data-and-threads-without-the-headache/

and the technique is also mentioned in the core data programming guide 'importing in batches'

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html#//apple_ref/doc/uid/TP40003174-SW1

like image 32
bandejapaisa Avatar answered Sep 27 '22 18:09

bandejapaisa