2011-12-26 4 views
38

Мое приложение использует Core Data (с помощью Magical Record) и довольно многопоточно использует NSOperation.Основные данные -existingObjectWithID: ошибка: вызывает ошибку 133000

Конечно, я очень осторожен, чтобы обойти только NSManagedObjectID между потоками/операциями.

Теперь, чтобы вернуться к соответствующему управляемому объекту в операции, я использую -existingObjectWithID:error: таким образом:

Collection *owner = (Collection *)[localContext existingObjectWithID:self.containerId error:&error]; 

Но что я получаю обратно ноль и error говорит, что это ошибка # 13300: NSManagedObjectReferentialIntegrityError.

Вот что документация говорит об этой ошибке:

NSManagedObjectReferentialIntegrityError 
Error code to denote an attempt to fire a fault pointing to an object that does not exist. 
The store is accessible, but the object corresponding to the fault cannot be found. 

Что не так в моем случае: этот объект существует. Действительно, если я повторяю все экземпляры этого объекта Collection с NSFetchRequest, я нахожу его среди них, а его NSManagedObjectID - это именно тот, который я передал -existingObjectWithID:error:.

Кроме того, если я использую -objectWithID:, вместо этого вернусь к объекту правильно.

Так что я чего-то не хватает. Вот несколько дополнительных замечаний/вопросов:

  • «объект, который не существует»: что это значит «существует» в этом предложении? «существуют» где? Это определенно «существует» в моем хранилище основных данных в этот момент.
  • «объект, соответствующий вине, не может быть найден»: что это означает «найденный» в этом предложении? «найдено» где? Это определенно «будет найдено» в моем хранилище основных данных в этот момент.

Так что, может быть, у меня что-то не хватает относительно того, что existingObjectWithID:error: делает? В документации указано:

If there is a managed object with the given ID already registered in the context, that object is returned directly; otherwise the corresponding object is faulted into the context. 
[...] 
Unlike objectWithID:, this method never returns a fault. 

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

  • Что было бы реалистичным сценарием, ведущим к NSManagedObjectReferentialIntegrityError?

Спасибо за любое просвещение.

+2

Вы когда-нибудь это выясняли? Я получаю ту же проблему, и мой объект определенно присутствует, и операция сохранения работает, но это происходит только эпизодически. – Adam

ответ

36

Проблема в том, что NSManagedObjectID Вы проходите временно. Вы можете проверить это, вызвав метод NSManagedObjectIDisTemporaryID. Из документации:

Returns a Boolean value that indicates whether the receiver is temporary.

Most object IDs return NO. New objects inserted into a managed object context are assigned a temporary ID which is replaced with a permanent one once the object gets saved to a persistent store.

Вы должны сначала сохранить изменения в постоянное хранилище, только тогда получить постоянный идентификатор перейти на другой контекст.

8

Когда вы используете несколько контекстов, вам необходимо сохранить контекст A перед передачей идентификатора управляемого объекта из контекста A в другой контекст B. Только после завершения сохранения этот объект будет доступен из контекста B.

-objectWithID: всегда будет возвращать объект non-nil, но он будет генерировать исключение, как только вы начнете его использовать, если в хранилище нет объекта поддержки. -existingObjectWithID:error: фактически запустит некоторый SQL и сделает I/O, если этот объект еще не зарегистрирован в контексте, в котором он используется.

+2

Это не так: когда я использую '-objectWithID:', я получаю правильный объект (как я писал): я могу использовать его, получить доступ к его свойствам, его отношениям, всем. И действительно, контекст, в котором он был создан только ранее, был сохранен. Тем не менее, '-existingObjectWithID: ошибка:' все еще не с ошибкой 133000. –

+0

Звучит очень странно. В обоих контекстах используется один и тот же NSPsistentStoreCoordinator? –

+1

Я «решил» это, выполнив сброс в управляемом объекте. Наверняка не идеальный, поэтому я с нетерпением жду других решений :-) – niklassaers

2

NSManagedObjectReferentialIntegrityError = 133000

NSManagedObjectReferentialIntegrityError Error code to denote an attempt to fire a fault pointing to an object that does not exist. The store is accessible, but the object corresponding to the fault cannot be found. Available in Mac OS X v10.4 and later. Declared in CoreDataErrors.h.

См. Это documentation.

This tutorial может быть вам полезна.

Таким образом, вероятная причина заключается в том, что вы пытаетесь получить объект, который не существует. Это происходит, когда вы пытаетесь создать objectid для не существующего объекта. Объектив будет возвращен вам, и когда вы попытаетесь получить объект с этим объектом, вы получите это исключение.

0

Я нашел их, имея дело с уведомлением NSManagedObjectContextDidSave. Многие объекты, удаленные другим контекстом, не могли быть извлечены, потому что (Ду!) Они были удалены! Однако некоторые из удаленных объектов оказались просто прекрасными, как те, которые я уже виноват в текущем контексте.

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

Смежные вопросы