启动Core Data应用程序时在后台配置NSFetchedResultsController [英] Configure NSFetchedResultsController in background when launching Core Data app
问题描述
我已经设置一个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秒),并与索引的属性。
所以我想能够显示一个 UIActivityIndicatorView
,应用程式正在等待载入。我知道如何通常在后台线程中加载核心数据对象,然后将它们合并回主线程,但是如何在后台线程中初始化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屋!