CoreData: "Висячая ссылка на недопустимый объект". ошибка
Я работаю над приложением Cocoa -Touch, он использует CoreData и имеет некоторые подклассы NSPersistentObject, созданные редактором модели XCode.
Я заметил, что в последнее время при сохранении контекста я получаю сообщение об ошибке, которое имеет в качестве информации пользователя следующую часть:
(gdb) po ui {
"Dangling reference to an invalid object." = <null>;
NSAffectedObjectsErrorKey = <dump #1 of someObject>;
NSLocalizedDescription = "Operation could not be completed. (Cocoa error 1550.)";
NSValidationErrorKey = <someKey pointing to someObject #1>;
NSValidationErrorObject = <dump #2 of someOtherObject which points to the dump #1 object>;
NSValidationErrorValue = { <list of someMoreObjects> };
}
В словаре пользовательской информации есть другие ключи.
Все дампы, которые я получаю, являются допустимыми объектами, я проверил их все.
NSValidationErrorObject
- это объект, который имеет NSSet
, который содержит объекты типов, сбрасываемых в NSAffectedObjectsErrorKey
и NSValidationErrorValue
. Но все эти объекты действительны.
Кроме того, это происходит случайным образом, иногда это случается, иногда нет, и иногда список, сбрасываемый в NSValidationErrorValue
, длиннее, иногда короче.
Я не знаю, почему это происходит, или что именно происходит с ошибкой. Кто-нибудь знает, что происходит? Любые идеи, которые могут вызвать эту странную ошибку?
Ответы
Ответ 1
Эта ошибка обычно возникает из-за того, что отношения устанавливаются неправильно часто, когда объект остается без необходимых взаимных отношений. Объект "свисает", потому что граф объекта говорит, что он должен находиться в отношениях, но он просто висит в пространстве, не связанном с каким-либо другим объектом. Объект по-прежнему действует в том смысле, что он является внутренним, но он не находится в допустимом месте на графике.
Ответ 2
Этот вопрос был задан некоторое время назад, но я просто столкнулся с ним. В моем случае это не было связано с неправильным установлением отношений технически. Это было связано с тем, что объект был создан в другом контексте, но не в другом потоке, а только в другом контексте в том же потоке.
Ищите проблемы с потоками, если вы делаете что-либо с потоком с Core Data.
Ответ 3
Скажем, у вас есть таблица "рецепты" и дочерняя таблица "ингредиенты". Затем вы создаете отношение "один ко многим" от рецепта к ингредиентам, а также создаете обратную взаимосвязь (один к одному) от ингредиентов к рецептам. Имеет смысл указать правило удаления "каскада" из таблицы рецептов, потому что, если вы удаляете рецепт, ингредиент также должен быть удален. Тем не менее, если вы укажете "no action" в правиле удаления в отношении отношения "один к одному" в ингредиентах, вы получите ошибку оборванных ссылок при попытке удалить ингредиент. Измените правило удаления для отношения "один-к-одному" к "nullify", и это должно устранить проблему.
Ответ 4
Я знаю это задолго до того факта, но я боролся с этой проблемой в базовой модели данных, у которой ВСЕ отношения установлены на Nullify. Удерживая эти болтающиеся ссылки, пока я не нашел один setPrimitiveValue
вместо setValue
, когда добавлял к отношениям. Будьте осторожны, с отношениями, вы должны быть уверены, что делаете правильные вещи, чтобы позволить Core Data поддерживать отношения для вас!
Ответ 5
У меня есть еще один пример того, как вызвать эту проблему: у меня есть MOC с типом concurrency NSMainQueueConcurrencyType
. Где-то в коде я делаю это:
__block MyObjectType1 *obj1;
[managedObjectContext performBlockAndWait:^{
obj1 = [NSEntityDescription insertNewObjectForEntityForName:@"Thing" inManagedObjectContext:managedObjectContext];
}];
// some other stuff
[self saveContext];
__block NSManagedObjectID *object1ID;
[managedObjectContext performBlockAndWait:^{
object1ID = [obj1 objectID];
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// do some slow-ish stuff
[managedObjectContext performBlockAndWait:^{
// create new object that has a relationship
NSManagedObject *obj1_copy = [managedObjectContext objectWithID:object1ID];
MyObjectType2 *obj2 = [NSEntityDescription insertNewObjectForEntityForName:@"OtherThing" inManagedObjectContext:managedObjectContext];
obj2.relatedThing = obj1_copy;
}];
[self saveContext];
});
Оказывается, иногда это терпит неудачу. Я все еще не понимаю, почему, но заставить заставить не-временный objectID
, похоже, сделать трюк:
[context performBlockAndWait:^{
NSError *error;
[managedObjectContext obtainPermanentIDsForObjects:@[obj1] error:&error];
object1ID = obj1.objectID;
}];
Ответ 6
У меня была та же проблема, и, наконец, я обнаружил, что проблема заключалась в том, что я устанавливал связь между двумя различными контекстами управляемых объектов.
Ответ 7
Моя проблема была решена с помощью этого кода:
[[CustomManagedObject managedObjectContext] performBlockAndWait:^{
NSError *error;
if (![[CustomManagedObject managedObjectContext] save:&error])
{
NSLog(@"Error in Saving: %@", [error.userInfo description]);
}
}];
Ответ 8
Добавляя к исходному ответу, может быть несколько причин для этого сбоя. Внимательно прочитайте описание ошибки. В моем случае я установил связь с объектом из другого контекста.
Ответ 9
Я столкнулся с этой проблемой, и проблема была связана с различными (или, скорее, нулевыми) контекстами управляемых объектов для объектов, у которых были отношения. В моем случае я создал связь между сущностями, когда у обоих были nil Contexts управляемых объектов, а затем добавлено одно из объектов в MOC и предполагается, что другое будет добавлено в MOC. Я предположил это из-за первых двух комментариев в верхнем ответе на этот поток SO, но это оказалось неправильным.
Итак, извлеченный урок: если вы добавите объект в MOC, другие объекты, у которых есть отношения к нему, не будут втягиваться в MOC вместе с ним. Вы должны добавить их в MOC, или Core Data не будет счастлив.