Master data: background fetch, NSFetchedResultsController, and sort time

The problem I am facing is the following:

I have a UITableView that I pass with data from NSFetchedResultsController , which fetches about 6,000 rows from the main data. fetchBatchSize of NSFetchRequest set to 20, and if I don't use any NSSortDescriptor , the fetch is fast enough to not block the UI thread.

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

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

So when the situation changes, the selection operation now takes about 3 seconds, because 6,000 rows are sorted. Obviously, during these seconds, the user interface is blocked and the user experience is terrible.

I know that I can make a selection in the background thread and then go to the object identifiers in the main thread, but in this case, how can I use the NSFetchedResultsController in the main thread (I also use it to observe data changes)?

I also have an indexed attribute by which I sort, but which only optimizes the search and does not perform sorting.

Any ideas would be greatly appreciated, thanks!

+8
sorting background core-data nsfetchedresultscontroller
source share
6 answers

First of all, NSFetchedResultsController is usually used in the main thread. And it does not support background selection so far Apple releases iOS 6.

Therefore, when you call executeFectch from NSFetchedResultController, you must "block" the main thread for a while. However, we want time to be minimal.

(As far as I recall, you should set the sort handle to NSFetchedResultController. So I'm not sure how you worked without setting the sort handle. Look at the class link)

I'm not sure if you are using the Sqlite Store. If so, I hardly believe your sort descriptor works. (see Master Data Programming Guide: Troubleshooting section). If not, storing so much data in memory would not be a good idea.

Finally, we have reached the point why it is slowing down. This view using "localizedCaseInsensitiveCompare:" makes your selection slow because comparing a Unicode string will be slow. (mentioned in WWDC 2010 master data specifications on iPhone).

Like many other applications, you must create a non-Unicode string field / property based on your "optionText" and sort based on this non-Unicode string property.

0
source share

How about using the NSFetchRequest batchSize ?

If you set a nonzero batch size, the collection of returned objects when sampling is broken into batches. When the entire query is executed, and the identifiers of all matching objects, but no more than the data of the batchSize objects, will be retrieved from the persistent storage at a time. The array returned from the request will be a proxy object that transparently refuses parties on demand. (In terms of a database, this is in-memory.)

+3
source share

I am doing package import in NSOperation, which uses a separate NSManagedObjectContext. Periodically, I save a second context that triggers a notification to update my main NSManagedContext, to which my NSFetchedResultsController is connected.

Perhaps a similar method can be applied to your selection.

Here is cocoa my girlfriend article:

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

and this method is also mentioned in the Import to Packages master data programming guide

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

+1
source share

Using a cache is likely to help get better performance.

I have the same problem, and I realized that the first call takes more than 3 seconds to retrieve, but twice by fetching it immediately shows the results.

0
source share

Displaying 6,000 rows in a single table might not be the best solution from a user's perspective. Perhaps you should add a filter table before. Like groups in an address book. This can lead to a better user experience if you manage to reduce the number of rows per filter to a more manageable number. This will decrease the loading time and time for scrolling.

I do not know what data you are showing, so there may be no way to show everything in one long list. For people, you can add options for gender and age groups. For cars, you can add a filter by brand and model ....

0
source share

You tried to run the performFetch: method in the background, or using

 [controller performSelectorInBackground:@selector(performFetch) withObject:nil]; 

or

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ [controller performFetch]; }); 
-4
source share

All Articles