15

我正在研究一些使用NSOperation导入数据的代码。我希望用户能够撤消在导入操作期间创建的NSManagedObject实例。取消在主线程中执行的核心数据插入

从我所知道的情况来看,对主线程执行的任何操作都不可能使用NSManagedObjectContext-undoManager。从使用核心数据编程指南节主题禁闭支持并发,我们有这两个条件:

  1. 只的objectID应通过托管对象上下文之间 (上 单独的线程)
  2. 被管对象 必须保存在 之前的上下文中才能使用objectID。

这是有道理的,因为管理对象需要从专用存储(NSManagedObjectContext)公共存储(NSPersistentStore),他们可以共享之前移动。

不幸的是,-save:消息还会导致撤消堆栈中的任何托管对象被删除。从同样的引导件的存储器管理使用核心数据部分:

托管具有挂起 变化(插入,缺失,或 更新)可以通过上下文 被保留,直到它们的上下文中的对象被发送保存:, 重置,回滚或dealloc消息, 或相应数量的撤销到 撤消更改。

我已经试过几件事情要解决这一限制,一切最终导致恢复大部分工作都发生在主线程的(和纺纱沙滩球),以获得任何线索撤消通过创建关闭对象工作主线程将非常感激。

-

的增强雷达已经提交:rdar://problem/8977725

+0

为什么不只是保留此操作插入的所有托管对象ID的日志?这样,如果用户想要回滚,可以简单地遍历并删除对象。如果您还必须回滚突变,那么记录关键/值更改也不难。看起来比试图将其放到撤销管理器中更简单。 – ImHuntingWabbits 2011-02-26 08:53:39

+0

关于上述评论,你会如何提出重做? – wbyoung 2011-06-20 16:06:46

回答

0

不是专家,但我想你会什么需要做的是创建第二个方面来进行操作,然后合并这两个环境在一起。您应该能够将合并作为撤消步骤进行管理。请注意,这只适用于将整个操作集作为一个撤消步骤,就用户而言。

+0

我已经在执行-mergeChangesFromContextDidSaveNotification:将导入上下文中的更改传播到主线程中的上下文。问题是合并使用已存在于持久性存储中的数据来调整对象图。主线程上的NSManagedObjectContext没有任何需要写入持久性存储的-insertedObjects或-updatedObjects。 – chockenberry 2011-02-09 17:39:00

0

假设您为后台线程使用单独的上下文,并且一旦完成后,将[[backgroundContext undoManager] undo]推送到前台线程的撤消堆栈上?我从来没有尝试过这样的事情,但从我的头顶来看,我想不出它不应该起作用的理由。

+0

你是什么意思“[[backgroundContext undoManager]撤销到前台线程的撤消堆栈”?从我可以告诉撤消堆栈的内容是私人的... – chockenberry 2011-02-09 03:39:41

+0

[[[foregroundContext undoManager] prepareWithInvocationTarget:[backgroundContext undoManager]] undo]; (实际上,您也需要保存backgroundContext ...) – 2011-02-09 05:01:31

0

一个选项可能是让您的导入线程持久化。即使线程完成导入,它也会进入空闲循环状态。这样您的线程ManagedObjectContext被保存在正确的线程中。然后,当用户希望撤消更改时,向该线程发送消息以使用undomanager。

2

这个答案可能会有点反复。如果我正确理解问题,那么您正在执行导入,但导入完成后,您希望用户能够选择从导入中保存的内容?

如果这是不正确的,请修正我的假设,我会更新这个答案。

如果它是正确的,那么你可以做的是:

  1. 你的背景对象创建更改为

    NSEntityDescription *myEntity = ... //Entity from your context 
    [[NSManagedObject alloc] initWithEntity:myEntity 
         insertIntoManagedObjectContext:nil]; 
    
  2. 存储这些实体在数组中。
  3. 根据需要将实体传递回主线程。
  4. 发布您不想保留的任何物品
  5. 致电[myMainContext insertObject:managedObject]任何您想保留的物品。
  6. NSManagedObjectContext上执行保存。

由于这些实体是不是一个NSManagedObjectContext的一部分,但它们只存在于内存中,并应该是线程安全的,因为他们还没有束缚于一个NSManagedObjectContext

这当然是理论上的,需要测试。但它应该实现你的目标。

0

这是令人难以置信可能你已经考虑了这一点,并使用现有的undoManager你可能只是寻找一个解决方案,但以防万一:

既然你插入的对象,而不是更新现有的,你做有权在导入每个批次时使用事务ID标记它们,在撤消的情况下在后台线程中删除它们。一个简单的递增NSNumber就足够标签。

不雅,但可行。