Configure NSFetchedResultsController in background when launching Core Data app

无人久伴 提交于 2019-12-22 17:39:09

问题


I have setup a Core Data app with the usual boilerplate code, and the RootViewController initializes the FRC by calling this:

- (NSFetchedResultsController *)fetchedResultsController 
{
    if (__fetchedResultsController != nil) 
    {
        return __fetchedResultsController;
    }
    // configure the fetchRequest, sectionKey and cacheName
    __fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest: fetchRequest 
                                                                    managedObjectContext: self.managedObjectContext 
                                                                      sectionNameKeyPath: sectionKey 
                                                                               cacheName: cacheName];
    return __fetchedResultsController;
}

All the sample code I've seen does this. However, I have a large data set and with over 15,000 entries, it takes about 5 seconds to launch the app on the iPhone 4S. This is with caching enabled (without it, it takes 11 seconds), and with indexed attributes.

So I want to be able to show a UIActivityIndicatorView which the app is waiting for this to load. I know how to generally load core data objects in the background thread and then merge them back into the main thread, but how can I initialize the FRC in the background thread so that all the objects are loaded and sectioned in the background?

I know I can load all the objects and partition them in a background thread into a custom dictionary and use that to present the data, but I would rather use the standard FRC calls and delegates.

Thanks.


回答1:


I'm not pretty sure what do you mean with using the NSFetchedResultsController in the background, but based on my experience you could just simply set batch size for your fetch request like the following:

[fetchRequest setFetchBatchSize:20];

In this manner, during startup are loaded the first 20 elements, when you scroll the next 20 and so on. In addition, you could just select the properties to fetch with - (void)setPropertiesToFetch:(NSArray *)values.

Another way is to have a (background) task that starts to fetch objects in background. I think that when fetched in background, the objects are cached in some way (but I'm not pretty sure) and so, you can access them from the main thread more rapidly.

Hope it helps.




回答2:


I think I've figured it out... you CAN create the FRC in the background thread and do the fetch in the main thread:

- (NSFetchedResultsController *)fetchedResultsController 
{
    if (__fetchedResultsController != nil) 
    {
        return __fetchedResultsController;
    }

    // create something to pass back to the first time FRC is initialized without fetching
    __block NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    aFetchedResultsController.delegate = self;
    [self.list_spinner startAnimating];

    dispatch_async(self.filterMainQueue, ^{

           NSFetchedResultsController *newFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest: fetchRequest 
                                                                                                         managedObjectContext: self.managedObjectContext 
                                                                                                           sectionNameKeyPath: sectionKey 
                                                                                                                    cacheName: cacheName];
           dispatch_async(dispatch_get_main_queue(), ^{ 
               // stop the spinner here
               [self.list_spinner stopAnimating];

               NSError *error = nil;
               if (![newFetchedResultsController performFetch:&error]) 
               {
                   NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                   [SimpleListAppDelegate showCoreDataError: @"SimpleListViewController - FRC"];
               }
               __fetchedResultsController = nil;
               newFetchedResultsController.delegate = self;
               __fetchedResultsController = newFetchedResultsController;
               [self.tableView reloadData];
           });
         });

    return aFetchedResultsController;
}


来源:https://stackoverflow.com/questions/10908592/configure-nsfetchedresultscontroller-in-background-when-launching-core-data-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!