Настройте 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,

Другой способ - создать (фоновую) задачу, которая начнет извлекать объекты в фоновом режиме. Я думаю, что при выборке в фоновом режиме объекты кэшируются каким-то образом (но я не совсем уверен), и поэтому вы можете получить к ним доступ из основного потока быстрее.

Надеюсь, поможет.

Другие вопросы по тегам