Настройте NSFetchedResultsController в фоновом режиме при запуске приложения Core Data
Я настроил приложение Core Data с обычным стандартным кодом, и RootViewController инициализирует FRC, вызывая это:
- (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;
}
Весь пример кода, который я видел, делает это. Тем не менее, у меня большой набор данных и более 15 000 записей, для запуска приложения на iPhone 4S требуется около 5 секунд. Это с включенным кэшированием (без него это занимает 11 секунд) и с индексированными атрибутами.
Так что я хочу иметь возможность показать UIActivityIndicatorView
которое приложение ожидает загрузки. Я знаю, как обычно загружать объекты основных данных в фоновом потоке, а затем объединять их обратно в основной поток, но как я могу инициализировать FRC в фоновом потоке, чтобы все объекты загружались и секционировались в фоновом режиме?
Я знаю, что могу загрузить все объекты и разделить их в фоновом потоке в пользовательский словарь и использовать их для представления данных, но я бы предпочел использовать стандартные вызовы и делегаты FRC.
Благодарю.
2 ответа
Я думаю, что я понял это... вы можете создать FRC в фоновом потоке и сделать выборку в основном потоке:
- (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;
}
Я не совсем уверен, что вы имеете в виду с использованием NSFetchedResultsController
в фоновом режиме, но, исходя из моего опыта, вы можете просто установить размер пакета для вашего запроса извлечения, как показано ниже:
[fetchRequest setFetchBatchSize:20];
Таким образом, при запуске загружаются первые 20 элементов, при прокрутке следующие 20 и так далее. Кроме того, вы можете просто выбрать свойства для выбора - (void)setPropertiesToFetch:(NSArray *)values
,
Другой способ - создать (фоновую) задачу, которая начнет извлекать объекты в фоновом режиме. Я думаю, что при выборке в фоновом режиме объекты кэшируются каким-то образом (но я не совсем уверен), и поэтому вы можете получить к ним доступ из основного потока быстрее.
Надеюсь, поможет.