Отладка NSObjectInaccessibleException - объект NSManagedObject с идентификатором: 0x123456789 был признан недействительным

У меня есть ошибка, с которой я пытаюсь отследить. Я считаю, что происходит то, что я удаляю объект из базовой базы данных, в то время как другой контекст управляемого объекта (в другом потоке) имеет ошибку на нем и получает "NSObjectInaccessibleException", когда он пытается выполнить ошибку.

Сценарий заключается в том, что у меня есть представление, которое обращается к данным через один контекст, тем временем в фоновом режиме, другая угроза - очистка устаревших записей из магазина. Фоновый поток должен только очищать объекты, которые не требуются для представления - это, очевидно, не так, но у меня возникают проблемы с отслеживанием того, что происходит. К тому времени, когда я вижу дефект, это слишком поздно, и это относительно редкий дефект, который в основном происходит только в поле.

Следовательно, мой вопрос: есть ли какие-либо трюки, которые мне не хватает при отладке CoreData - можно ли отслеживать время жизни объектов из одного контекста в другом? То есть когда я удаляю свой объект, есть ли простой способ увидеть, имеют ли какие-либо другие контексты ссылку на тот же самый объект? Используя это, я мог бы создать некоторый тестовый код, чтобы проверить свою логику и найти ошибку.

Ответ 1

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

Исправление было таким, как описано в блоге Jake blog - установите делегат на нуль, когда вы закончите с видом карты.

Ответ 2

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

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

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

Я новичок в Core Data, поэтому, вероятно, лучший/более умный способ сделать это, но я думаю, что это исправило проблему для меня.

Ответ 3

Я тоже столкнулся с этой проблемой. Я сделал несколько рефакторингов, чтобы следить за шаблоном Apple "find-or-create" для массового импорта данных. Я создал новый контекст, посвященный импорту, установив неподанное значение nil, как было предложено. Итак:

// create a new special context for the bulk import of data
NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] init];
[importContext setPersistentStoreCoordinator:_persistentStoreCoordinator];

// avoid tracking for undo/redo operations
[importContext setUndoManager:nil];

то я создал fetchRequest для извлечения идентификаторов объектов, хранящихся в базе данных, и внутри цикла импорта я тестировал идентификатор объекта, чтобы найти, содержался ли он внутри массива идентификаторов, найденных... проблема заключалась в том, что в заданный интервал Я сохранил importContext и сбросил его. И поскольку я ошибочно ссылался на importContext, а не на defaultContext, я получаю эту ошибку. Я исправил, просто изменив:

NSArray *storedObjects = [importContext executeFetchRequest:checkRequest error:&fetchError];

с:

NSArray *storedObjects = [defaultContext executeFetchRequest:checkRequest error:&fetchError];

Ответ 4

Каков второй контекст, когда он пытается сбой в объекте, который был удален из постоянного хранилища?

Это звучит как ошибка, которая может состоять из двух частей: вы не объединяете изменения из вашего равноправного контекста, и у вас есть логическая ошибка, из-за которой вы используете объект в потоке B, который был удален в потоке A.

Обычно вам нужно объединить изменения из однорангового контекста с помощью -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:].