【问题标题】:CoreData: "Cannot delete object that was never inserted."CoreData:“无法删除从未插入的对象。”
【发布时间】:2013-11-24 16:39:17
【问题描述】:

我这辈子都无法解决这个问题,但 CoreData 不断向我抛出错误。

无法删除从未插入的对象。

这是我的应用程序周期的要点:

1/ 推送 ViewController。

2/ 从应用委托中获取托管对象上下文。

FLAppDelegate *appDelegate = (FLAppDelegate *)[[UIApplication sharedApplication] delegate];
    self.managedObjectContext = appDelegate.managedObjectContext;

3/ 检查Session是否存在。

4/ 不存在Session,创建一个新的。

    self.session = nil;
            self.session = [NSEntityDescription insertNewObjectForEntityForName:@"Session" inManagedObjectContext:self.managedObjectContext];

    //Set attributes etc...

//Keep a reference to this session for later
    [[NSUserDefaults standardUserDefaults] setURL:self.session.objectID.URIRepresentation forKey:kKeyStoredSessionObjectIdUriRep];
            [[NSUserDefaults standardUserDefaults] synchronize];

            NSError *error = nil;
            if (![self.managedObjectContext save:&error])
            {
                //Handle error if save fails
            }

5/ 弹出视图控制器。

6/ 返回 ViewController。

7/ 再次检查Session 是否存在。

8/ 找到Session! (通过查看NSUserDefaults 以获取我们存储以供以后参考的那个)。所以我得到了我之前创建的Session,然后让用户选择删除那个并重新开始或继续那个。

NSURL *url = [[NSUserDefaults standardUserDefaults] URLForKey:kKeyStoredSessionObjectIdUriRep];
    if (url) //Found existing flight session
    {
        NSManagedObjectID *objId = [self.managedObjectContext.persistentStoreCoordinator managedObjectIDForURIRepresentation:url];
        NSManagedObject *obj = [self.managedObjectContext objectWithID:objId];
        self.session = (Session *)obj;

        //Ask the user if they want to continue with this session or discard and start a new one
    }

9/ 选择删除这个Session 并开始一个新的。

10/ 问题从这里开始!我删除了我对这个 Session 的引用,因为它不再相关,并尝试删除该对象,然后保存这些更改。

[[NSUserDefaults standardUserDefaults] removeObjectForKey:kKeyStoredSessionObjectIdUriRep];
            [[NSUserDefaults standardUserDefaults] synchronize];

            [self.managedObjectContext deleteObject:self.session];
            NSError *error = nil;
            if (![self.managedObjectContext save:&error])
            {
                //Error!
            }

11/ 好了,当我尝试运行 save 方法时,它崩溃并抛出错误:NSUnderlyingException = "Cannot delete object that was never inserted.";

我不知道为什么会这样说,因为每当我创建一个对象并创建引用时,我似乎都会保存该对象,然后从该引用中检索对象,但随后删除只会破坏一切。

【问题讨论】:

  • 我会尝试存储 objectID 而不是 URI 表示。不知道这是否能解决您的问题,但对我来说这似乎更强大。
  • 保存会话时,如果托管对象上下文不为零,则检查调试器。
  • 你在哪里断言你的 managedObjectContext 与主线程相关联?您在哪里断言您的方法将在主线程上执行?

标签: ios objective-c core-data


【解决方案1】:

问题出在您的第 4 步。在此步骤中,您

  1. 创建Session
  2. 将其托管对象 ID 保存为用户默认值
  3. 保存对托管对象上下文的更改。

失败的原因是当您创建一个新的托管对象时,它有一个临时对象 ID,该 ID 仅在您保存更改之前有效。保存更改后,它会立即获得一个新的永久对象 ID。您正在保存临时对象 ID,但是当您稍后查找它时,它不再有效。

您可以通过更改第 4 步中的操作顺序来解决此问题,以便您:

  1. 创建Session
  2. 保存对托管对象上下文的更改
  3. Session 的对象 ID 保存为用户默认值

这样,当您将值保存为用户默认值时,您将拥有一个永久 ID。

【讨论】:

  • 就是这样!谢谢汤姆。
  • 这很有效,谢谢,但参考文档没有说明临时 objectID 既不是 NSEntityDescription 也不是 NSManagedObject。另外,一旦没有对象了,为什么给一个临时的 objectId 会返回 nil 以外的任何东西?
  • NSManagedObjectID 的文档中提到了临时 ID,以及其他地方。 objectWithID 方法被记录为总是返回一个对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
相关资源
最近更新 更多