Существующая тупиковая ситуация 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
Это подозрительно похоже на то, что цикл сохранения препятствовал освобождению объекта, тем самым вызывая его постоянное существование в родительском контексте и тупиковую ситуацию, пытавшуюся вызвать ошибку.