【问题标题】:CoreData: "Dangling reference to an invalid object." errorCoreData:“对无效对象的悬空引用。”错误
【发布时间】:2011-01-01 11:56:53
【问题描述】:

我正在开发一个 Cocoa-Touch 应用程序,它使用 CoreData 并有一些由 XCode 模型编辑器生成的 NSPersistentObject 子类。

我最近注意到,在保存上下文时,我收到一个错误,其中包含以下部分的用户信息:

(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 的对象,其中包含在NSAffectedObjectsErrorKeyNSValidationErrorValue 中转储的类型的对象。但所有这些对象都是有效的。

此外,这会随机发生,有时会发生,有时不会发生,有时NSValidationErrorValue 中转储的列表更长,有时更短。

我不知道为什么会这样,或者错误到底是什么。有谁知道发生了什么?有什么想法可能导致这个奇怪的错误吗?

【问题讨论】:

    标签: iphone cocoa-touch core-data


    【解决方案1】:

    我遇到了这个问题,这个问题与具有关系的实体的不同(或者更确切地说是一个 nil)托管对象上下文有关。在我的例子中,当两个实体都具有 nil 托管对象上下文时,我创建了实体之间的关系,然后将其中一个实体添加到 MOC,并假设另一个实体也将添加到 MOC。我假设这是因为前两个 cmets 对这个 SO thread 的最佳答案,但最终是错误的。

    因此吸取了教训:如果您将实体添加到 MOC,则与其有关系的其他实体不会与它一起被拖入 MOC。您还必须将它们添加到 MOC 中,否则 Core Data 将不高兴。

    【讨论】:

      【解决方案2】:

      除了原始答案之外,发生此崩溃可能有几个原因。仔细阅读错误描述,在我的情况下,我正在与另一个上下文中的对象建立关系。

      【讨论】:

        【解决方案3】:

        我的问题已使用此代码解决:

        [[CustomManagedObject managedObjectContext] performBlockAndWait:^{
                NSError *error;
                if (![[CustomManagedObject managedObjectContext] save:&error])
                {
                    NSLog(@"Error in Saving: %@", [error.userInfo description]);
                }
            }];
        

        【讨论】:

          【解决方案4】:

          我有另一个如何导致此问题的示例:我有一个并发类型为NSMainQueueConcurrencyType 的 MOC。在代码中的某处我这样做:

          __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;
          }];
          

          【讨论】:

          • 我应该说saveContext 本身使用了performBlockAndWait:,所以如果我正确理解队列并发类型,在这里使用应该是安全的......
          【解决方案5】:

          我有同样的问题,最后我发现问题是我在两个不同的托管对象上下文之间设置关系。

          【讨论】:

            【解决方案6】:

            不久前有人问过这个问题,但我只是碰到了它。在我的情况下,这不是由于技术上设置不正确的关系。这是由于在不同的上下文中创建的对象,请注意不是在不同的线程上,只是在同一线程上的不同上下文。

            因此,如果您使用 Core Data 对线程进行任何操作,请查找线程问题。

            【讨论】:

            • 我遇到了类似的问题,这是由于多线程核心数据代码有多个 NSManagedObjectContext。你建议我在哪里寻找线程问题?
            • 我正是因为混淆了上下文而遇到了这个问题。只需确保您只在属于同一上下文的对象之间建立关系。
            • 这也是我的问题。我非常困惑,因为所有的关系似乎都是有效的(并且在多对多的情况下双方都设置为“无效”)......但我不小心在一个实例中跳过了一个上下文,这就是结束。
            【解决方案7】:

            我知道这是很久以后的事了,但我一直在核心数据模型上解决这个问题,该模型将所有关系都设置为 Nullify。一直获取这些悬空引用,直到我在添加关系时找到一个 setPrimitiveValue 而不是 setValue。小心,对于关系,你必须确保你做正确的事情让 Core Data 为你维护关系!

            【讨论】:

              【解决方案8】:

              假设您有一个表“recipes”和一个子表“ingredients”。然后,您创建从食谱到配料的一对多关系,并创建从配料到食谱的反向关系(一对一)。从食谱表中指定“级联”的删除规则是有意义的,因为如果您删除一个食谱,该成分也应该被删除。但是,如果您在成分中的一对一关系的删除规则中指定“无操作”,当您尝试删除成分时,您将收到悬空引用错误。将一对一关系的删除规则更改为“无效”,这应该可以解决问题。

              【讨论】:

              • 谢谢,你拯救了我的一天! “不采取行动”规则是我关系中的问题。
              • 是的,它也拯救了我的一天。
              • 完美解决方案.. 非常感谢
              【解决方案9】:

              这个错误通常是因为当一个对象没有必要的互惠关系时,关系设置不正确。该对象是“悬空的”,因为对象图表明它应该处于关系中,但它只是悬挂在与任何其他对象无关的空间中。该对象仍然有效,因为它是内部一致的,但它不在图中的有效位置。

              【讨论】:

              • 可能,但这是解决细节的问题之一。该警告可能会告诉您问题的根源。对于复杂的数据结构,您应该将警告视为错误,因为警告通常会告诉您,如果情况合适,某些事情可能会失败。检查 A 和 B 对 C 的删除规则是否相同。在错误转储中,哪些对象是 A、B 或 C 类的“someObject”和“someOtherObject”?
              • 我在 C 到 A 和 B 中创建了虚拟关系,正确设置了反向关系并将删除操作设置为级联。现在没有更多警告了,但我仍然得到同样的错误:(
              • 顺便说一句,NSValidationErrorObject 是 C 类型,而 NSAffectedObjectsErrorKey 和 NSValidationErrorValue 都是 B 的同一个实例。
              • 不知道你是怎么解决的?我会感兴趣的。
              • 现在真的是一个好的答案吗?我发现这个答案很有帮助。谢谢 TechZen。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-12-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-08-18
              相关资源
              最近更新 更多