CoreData: «свисающая ссылка на недопустимый объект». ошибка - PullRequest
25 голосов
/ 05 января 2010

Я работаю над приложением 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, длиннее, иногда короче.

Понятия не имею, почему это происходит, или в чем именно заключается ошибка. Кто-нибудь знает, что происходит? Есть идеи, что может вызвать эту причудливую ошибку?

Ответы [ 9 ]

25 голосов
/ 05 января 2010

Эта ошибка обычно возникает из-за того, что отношение устанавливается неправильно, когда объект остается без необходимого взаимного отношения. Объект «болтается», потому что граф объектов говорит, что он должен быть в отношениях, но он просто висит в пространстве, не связанном с любым другим объектом. Объект все еще действителен в том смысле, что он является внутренним согласованным, но он не находится в допустимом месте на графике.

18 голосов
/ 15 марта 2012

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

Так что ищите проблемы с потоками, если вы что-то делаете с потоками с Core Data.

11 голосов
/ 09 октября 2010

Допустим, у вас есть таблица «Рецепты» и дочерняя таблица «Ингредиенты». Затем вы создаете отношение «один ко многим» от рецепта к ингредиентам, а также создаете обратную связь (один к одному) от ингредиентов к рецептам. Имеет смысл указать правило удаления «каскад» из таблицы рецептов, потому что если вы удалите рецепт, ингредиент также должен быть удален. Однако, если вы укажете «не предпринимать никаких действий» в правиле удаления в отношении «один-к-одному» в ингредиентах, вы получите сообщение об ошибочной ссылке при попытке удалить ингредиент. Измените правило удаления в отношении «один-к-одному» на «обнулить», и это должно исправить проблему.

5 голосов
/ 08 октября 2011

Я знаю, что это долго после этого, но я боролся с этой проблемой в базовой модели данных, в которой для ВСЕХ отношений установлено значение Nullify. Продолжал получать эти свисающие ссылки, пока не нашел один setPrimitiveValue вместо setValue, когда добавлял отношения. Будьте осторожны с отношениями, вы должны быть уверены, что делаете правильно, чтобы Core Data поддерживала отношения для вас!

3 голосов
/ 30 марта 2013

У меня есть другой пример того, как вызвать эту проблему: у меня есть MOC с типом параллелизма 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;
}];
1 голос
/ 25 февраля 2013

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

0 голосов
/ 13 декабря 2016

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

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

0 голосов
/ 16 ноября 2016

Добавление к исходному ответу может привести к нескольким причинам возникновения этого сбоя. Внимательно прочитайте описание ошибки. В моем случае я настраивал отношения с объектом из другого контекста.

0 голосов
/ 10 февраля 2015

Моя проблема была решена с помощью этого кода:

[[CustomManagedObject managedObjectContext] performBlockAndWait:^{
        NSError *error;
        if (![[CustomManagedObject managedObjectContext] save:&error])
        {
            NSLog(@"Error in Saving: %@", [error.userInfo description]);
        }
    }];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...