启动Core Data应用程序时在后台配置NSFetchedResultsController [英] Configure NSFetchedResultsController in background when launching Core Data app

查看:161
本文介绍了启动Core Data应用程序时在后台配置NSFetchedResultsController的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 我已经设置一个Core Data应用程序与通常的样板代码,并且RootViewController通过调用这个初始化FRC: - (NSFetchedResultsController *)fetchedResultsController 
{
if(__fetchedResultsController!= nil)
{
return __fetchedResultsController;
}
//配置fetchRequest,sectionKey和cacheName
__fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:sectionKey
cacheName:cacheName];
return __fetchedResultsController;
}

我看到的所有示例代码都是这样。然而,我有一个大的数据集和超过15,000条目,需要大约5秒钟在iPhone 4S上启动的应用程序。这是与缓存启用(没有它,它需要11秒),并与索引的属性。



所以我想能够显示一个 UIActivityIndi​​catorView ,应用程式正在等待载入。我知道如何通常在后台线程中加载核心数据对象,然后将它们合并回主线程,但是如何在后台线程中初始化FRC,以便在后台加载和分段所有对象?



我知道我可以加载所有对象,并在后台线程中将它们分割成自定义字典,并使用它来呈现数据,但我宁愿使用标准FRC呼叫和代表。



感谢。

解决方案

我想我想...你可以在后台线程中创建FRC并在主线程中执行fetch:

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

//创建一些东西传回第一次FRC被初始化而不提取
__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(@未解析的错误%@,%@,错误,[错误userInfo]);
[SimpleListAppDelegate showCoreDataError:@SimpleListViewController - FRC];
}
__fetchedResultsController = nil;
newFetchedResultsController.delegate = self;
__fetchedResultsController = newFetchedResultsController;
[self.tableView reloadData];
});
});

return aFetchedResultsController;
}


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.

解决方案

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;
}

这篇关于启动Core Data应用程序时在后台配置NSFetchedResultsController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆