【问题标题】:An NSManagedObjectContext cannot delete objects in other contextsNSManagedObjectContext 不能删除其他上下文中的对象
【发布时间】:2011-08-17 08:23:20
【问题描述】:

我有两个实体,每个实体都显示在自己的 UITableView 部分。

我启用了编辑功能,允许用户通过向右滑动来删除行。这适用于第一个实体,但是当我尝试删除第二个实体中的对象时,我收到此错误:

An NSManagedObjectContext cannot delete objects in other contexts

我明白错误所说的内容,但我看不出它在这里是如何应用的。我使用对我的上下文的保留引用来创建、获取和删除数据库中的所有对象,所以我确信只有一个上下文。我也没有使用多个线程。知道会发生什么吗?

【问题讨论】:

    标签: iphone core-data nsmanagedobject


    【解决方案1】:

    补充dominostars 给出的答案,在使用 SwiftUI 时,只需像@Environment(\.managedObjectContext) var moc 一样声明一次对托管对象上下文的引用,然后将此引用传递给需要访问的所有其他视图。不要两次声明引用。

    【讨论】:

      【解决方案2】:

      我不确定它是否回答了您的问题,但是当我尝试在 Swift 中删除 CoreData 对象时,我遇到了类似的崩溃。我修复了它调用 objectId

      func deleteNumber(phoneNumber: PhoneNumber) {
          let objectToDelete = container.viewContext.object(with: phoneNumber.objectID)
          container.viewContext.delete(objectToDelete)
      
      //save context
          if container.viewContext.hasChanges {
              do {
                  try container.viewContext.save()
              } catch {
                  print("An error occurred while saving: \(error)")
              }
          }
      }
      

      【讨论】:

        【解决方案3】:

        您从中提取NSManagedObject 的上下文是否与您用于删除NSManagedObject 的上下文相同?如果没有,您需要:

        • 拥有对同一NSManagedObjectContext 的共享引用,以便从创建或获取对象的同一上下文中删除该对象。如果您不使用多线程,那么您只需在代码中调用一次[[NSManagedObjectContext alloc] init]

        • 如果您必须使用NSManagedObjectContext 的两个不同实例,则从您从第一个上下文中获得的NSManagedObject 中获取objectID,以便稍后调用:

          [context deleteObject:[context objectWithID:aObjectID]];
          

          NSManagedObjectID 在上下文之间是相同的,但 NSManagedObject 本身不是。

        【讨论】:

        • 我在应用程序委托中使用 managedObjectContext ivar(在我创建项目时由 xcode 放在那里)。导致错误引用的代码使用 [[[UIApplication sharedApplication] delegate] managedObjectContext]。整个应用程序中只使用了一个实例。
        • 刚刚修好了。这是一个错字 - 与上下文无关。抱歉,感谢您的帮助!
        • 对于在 Google 搜索中遇到此问题的任何其他人,如果您将无效对象或其他输入错误的代码传递给 [managedObjectContext deleteObject];,您可能会收到此错误我偶然传递了一个 NSNumber*,它给了我这个错误,而不是告诉我应该传递NSManagedObject*
        • 只是为了添加到@RileyDutton 答案 - 如果您仅获取他的托管对象 ID,则无法删除对象(通过 ...setResultType:NSManagedObjectIDType] 获取 NSFetchRequest
        • @RileyDutton 是的,你是绝对正确的,即使我也错误地传递了错误的对象并一次又一次地得到同样的错误,但是我看到你的解释得到了真正的原因谢谢!!!
        【解决方案4】:

        我用这个:

          func delete(object: YourManagedObject) {
            guard let context = object.managedObjectContext else { return }
        
            if context == self.viewContext {
              context.delete(object)
            } else {
              self.performBackgroundTask { context in
              context.delete(object)
            }
          }
        
          try? self.viewContext.save()
        }
        

        基本上,您要删除的对象很可能是由 NSPersistentContainerviewContext 提供的。所以试图从私有后台上下文中删除是行不通的。

        【讨论】:

        • 很好的答案,看来它已经解决了我的问题,不得不稍微修改一下
        【解决方案5】:

        此答案阐述了 Riley Dutton 在 cmets 中描述的错误消息具有误导性的案例。

        当您将不是 NSManagedObject 子类的对象传递给deleteObject: 时,将显示错误消息。 Riley 只是通过显式传入错误的对象来解决问题,但我通过 Core Data 更改解决了问题。

        我的项目部署目标设置为 7.0,即使在 iOS 9.3 上运行,此代码也能正常运行:

        NSArray *entries = @[self.colorList.colors, self.emotionList.emotions, self.shapeList.shapes];
            for (id entry in entries) {
                [[self managedObjectContext] deleteObject:entry];
            }
        

        当我将项目部署目标更新到 9.3 时,我开始收到错误消息。

        这里是entry的描述:

        Relationship 'colors' fault on managed object (0x7fd063420310) <MyColorList: 0x7fd063420310> (entity: MyColorList; id: 0xd000000000640006 <x-coredata://12556DEF-F77E-4EFF-AAE6-55E71A3F5420/MyColorList/p25> ; data: {
            attachedThing = "0xd0000000000c0004 <x-coredata://12556DEF-F77E-4EFF-AAE6-55E71A3F5420/MyThing/p3>";
            colors = "<relationship fault: 0x7fd063468f30 'colors'>";
        })
        

        看起来 Apple 更改了 Core Data 何时触发故障并实际从持久存储协调器中提取数据的规则。

        这个修改解决了问题:

        NSArray *entries = @[self.colorList.colors, self.emotionList.emotions, self.shapeList.shapes];
            for (id entry in entries) {
                for (id e in entry) {
                    [[self managedObjectContext] deleteObject:e];
                }
            }
        

        目前我不知道这是否是解决这个问题的理想方式,或者是否有更规范的方式告诉Core Data触发故障并从磁盘读取数据。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-08-24
          • 1970-01-01
          • 1970-01-01
          • 2018-10-10
          • 1970-01-01
          • 2017-04-24
          相关资源
          最近更新 更多