Отладка NSObjectInaccessibleException - NSManagedObject с ID: 0x123456789 был признан недействительным - PullRequest
11 голосов
/ 09 августа 2009

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

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

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

Ответы [ 4 ]

7 голосов
/ 28 октября 2009

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

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

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

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

2 голосов
/ 06 июля 2011

Я тоже столкнулся с этой проблемой. Я провел некоторый рефакторинг, чтобы следовать шаблону Apple «найди или создай» для массового импорта данных. Я создал новый контекст, посвященный импорту, установив для undomanager значение 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];
1 голос
/ 31 октября 2009

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

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

1 голос
/ 11 августа 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...