Существующая тупиковая ситуация ObjectWithID с NSPrivateQueueConcurrencyType

Я бегу, чтобы заморозить (тупик?) С NSPrivateQueueConcurrencyType тип параллелизма, а не с NSMainQueueConcurrencyType,

Моя контекстная инициализация:

_managedObjectContext = [[NSManagedObjectContext alloc] 
initWithConcurrencyType:NSPrivateQueueConcurrencyType];  
[_managedObjectContext setPersistentStoreCoordinator:coordinator];

Проблемный код:

NSManagedObjectID *managedObjectID = [self managedObjectIDForEntity:entity 
withParseObjectId:object.objectId];  
managedObject = [context existingObjectWithID:managedObjectID error:error];

Обратный след:трассировка

Ссылка на проект Github и открытая проблема для некоторого контекста в проблему.

1 ответ

Решение

Ты выстрелил себе в лицо.

executeFetchRequest:error: создает отдельный дочерний контекст, над которым он выполняет некоторую работу (в то время как очередь родителя блокируется). Эта работа включает в себя синхронную отправку работы в очередь родителя (через insertOrUpdateObjects:).

Это потому что NSManagedObjectContext-existingObjectWithId: с вложенными контекстами отправляет в очередь родителя, чтобы выполнить объекты, сброшенные в родительский контекст. К сожалению, вы уже заблокировали родительскую очередь своим performBlockAndWait на дочернем контексте.

Великая грусть наступает.


Редактировать: Мысли о возможном решении

Проблема здесь вызвана использованием вложенных контекстов с различными очередями. Я не уверен, что понимаю мотивацию использования вложенного контекста в этой ситуации, если только не предоставлен контекст NSMainQueueConcurrencyType.

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

Возможно, что AFIncrementalStore каким-то образом гарантирует изоляцию графа в этой ситуации. Я нашел эту проблему поданной против AFNetwork:

https://github.com/AFNetworking/AFIncrementalStore/commit/1f822279e6a7096327ae56a2f65ce8e2ff36da83

Это подозрительно похоже на то, что цикл сохранения препятствовал освобождению объекта, тем самым вызывая его постоянное существование в родительском контексте и тупиковую ситуацию, пытавшуюся вызвать ошибку.

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