iOS -MagicalRecord / AFNetworking / NSFetchedResultsController -фоновый процесс ресинхронизации вызывает вечное зависание

Итак, цель, которую я пытаюсь достичь

— это процесс синхронизации, который должен выполняться в фоновом режиме с использованием AFNetworking и Magical Record, но вызывает постоянное зависание, когда контроллер представления, подключенный к NSFetchedResultsController, в данный момент открыт или был открыт (, но выскочил ).

Приложение синхронизируется при первом открытии телефона пользователем, а затем всегда использует данные в хранилище сохраняемости Core Data через структуру Magical Record. Затем, когда пользователь хочет убедиться, что данные являются самой последней версией, он заходит в настройки и нажимает «Re -Sync», что приводит к выполнению следующего кода:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
    [[CoreDataOperator sharedOperator] commenceSync:self];
});

Это запускает процесс синхронизации с использованием одноэлементного подкласса CoreDataOperator (NSObject --, может быть, это должен быть NSOperation? ), который запускает следующий код:

[[ApiClient sharedClient] getDataRequest];

который затем запускает этого плохого мальчика в одноэлементном подклассе AFHTTPClient:

[[ApiClient sharedClient] postPath:url parameters:dict
 success:^(AFHTTPRequestOperation *operation, id responseObject) {
 [request.sender performSelector:request.succeeded withObject:response];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
 [request.sender performSelector:request.failed withObject:response];
}
 ];

который фактически говорит :AFHTTPClient публикует эту информацию и, когда это удается, возвращает информацию предоставленному селектору (Я понимаю, что это общий, но запрос не проблема)

ТЕПЕРЬ, AFNetworking кодируется таким образом, что все селекторы завершения (, в данном случае конкретно успех и неудача ), вызываются в основном потоке; поэтому, чтобы предотвратить блокировку основного потока, код, обрабатывающий ответ и подготавливающий его к сохранению, отправляется обратно в фоновый поток :

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    id responseData;
    [self clearAndSaveGetData:responseData];
});

. Затем это вызывает функцию, которая вызывает сохранение с использованием среды Magical Record (, все еще в фоновом потоке ):

NSManagedObjectContext *localContext = [NSManagedObjectContext contextForCurrentThread];

[DATAENTITY truncateAllInContext:localContext];
<!--- PROCESS DATA INTO DATAENTITY -->
[localContext saveNestedContexts];

. Я выбрал saveNestedContexts, потому что, поскольку я работаю в фоновом режиме,Я хотел, чтобы он был доведен до контекстов по умолчанию, которые, как я предполагаю, являются родительским контекстом? (но до сих пор это не было проблемой ).

Теперь эти данные могут состоять из тысяч и тысяч строк, поэтому я использую NSFetchedResultsController для безопасного и эффективного доступа к этим данным, и они используются в другом контроллере представления, чем настройки или главная страница.

Вот три случая:

  1. ViewController, содержащий FRC, не был доступен (не виден и не был виден ранее)-фоновая синхронизация работает без нареканий, за исключением небольшого лага из-за сохранения стека.
  2. Был получен доступ к ViewController, содержащему FRC, и в настоящее время он виден-процесс фоновой синхронизации зависает из-за того, что FRC получает обновления контекста.
  3. ViewController, содержащий FRC, был ранее доступен, но в настоящее время он не виден (VC был извлечен с использованием следующего кода:[self.navigationController popViewControllerAnimated:YES];)И FRC установлен на ноль в ViewDidUnload-процесс фоновой синхронизации зависает из-за того, что FRC получает обновления контекста (, как и в случае 2 ).

[PS :после зависания на несколько минут я закрываю отладчик, и он выдает мне SIGKILL на следующий код, поэтому я предполагаю, что FRC получает обновления контекста, что приводит к зависанию:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{
    UITableView *tableView = controller == self.fetchedResultsController ? self.tableView : self.searchDisplayController.searchResultsTableView;
    [tableView endUpdates]; <---- SIGKILL
}

Другая важная информация для заметок:

  • Я использую 2 отдельных FRC, один для обычных ВСЕХ данных и один для поиска
  • Я использую кеш как для FRC, так и для отдельного поиска FRC, который очищается в соответствующее время (перед этим обновлением контекста)
  • FRC извлекаются в основном потоке (, что вызывает небольшое зависание, когда есть ТЫСЯЧИ строк данных ), и я изучал выборку в фоновом режиме, однако в настоящее время это не реализовано.

ВОПРОС (с):

  1. Почему происходит это зависание, где ВК видна или выскочила?
  2. Как я могу сделать так, чтобы FRC не прослушивал сохранение, а использовал то, что у него есть, до завершения сохранения, а затем обновлял данные (, если только это уже не происходит и не вызывает зависание )?
  3. Будет ли реализована фоновая выборка (, потому что задержка при открытии VC с помощью FRC для доступа к тысячам строк данных создает заметную задержку, даже с кэшем и уменьшенными заголовками предикатов/разделов -от 1 до 4 секунд. )быть жизнеспособным? Слишком сложно? Как это сделать?

Спасибо, надеюсь, я был достаточно подробным в своем вопросе.

6
задан Perception 4 March 2013 в 16:54
поделиться