我正在研究一些使用NSOperation
导入数据的代码。我希望用户能够撤消导入操作期间创建的NSManagedObject
实例。
据我所知,对于从主线程执行的任何操作,都不可能使用NSManagedObjectContext
-undoManager
。从使用线程限制来支持并发的核心数据编程指南部分,我们有以下两个条件:
- 只应传递objectID 托管对象上下文之间(on 单独的线程)
- 托管对象 必须先保存在上下文中 可以使用objectID。
醇>
这是有道理的,因为托管对象需要从私有存储(NSManagedObjectContext
)移动到公共存储(NSPersistentStore
)才能共享。
不幸的是,-save:
消息还会导致撤消堆栈中的任何托管对象被删除。从同一指南的使用核心数据的内存管理部分:
具有待处理的托管对象 变化(插入,删除或 更新)由其上下文保留 直到他们的上下文发送保存: 重置,回滚或dealloc消息, 或适当数量的地址 撤消更改。
我已经尝试了几个方法来解决这个限制,并且所有事情最终都会导致主线程(以及旋转沙滩球)上发生的大量工作。任何线索都要撤消使用主线程创建的对象非常感谢。
-
已提交增强型雷达:rdar://problem/8977725
答案 0 :(得分:2)
这个答案可能会有点来回。如果我正确理解了这个问题,那么您正在进行导入,但是在导入完成后,您希望用户能够选择从导入中保存的内容吗?
如果这不正确,请修正我的假设,我会更新此答案。
如果它是正确的那么你可以做的是:
将您的背景对象创建更改为
NSEntityDescription *myEntity = ... //Entity from your context
[[NSManagedObject alloc] initWithEntity:myEntity
insertIntoManagedObjectContext:nil];
[myMainContext insertObject:managedObject]
。NSManagedObjectContext
。由于这些实体不是NSManagedObjectContext
的一部分,但它们只存在于内存中, 应该是线程安全的,因为它们尚未绑定到NSManagedObjectContext
。
这当然是理论上的,需要进行测试。但它应该实现你的目标。
答案 1 :(得分:0)
不是专家,但我认为您需要做的是创建第二个上下文来执行操作,然后将两个上下文合并在一起。您应该能够将合并作为撤消步骤进行管理。请注意,这仅在您将整个操作集视为一个撤消步骤时才有效。就用户而言。
答案 2 :(得分:0)
假设您为后台线程使用单独的上下文,一旦完成,将[[backgroundContext undoManager] undo]
推送到前台线程的撤消堆栈?我从来没有尝试过这样的事情,但是我无法想到它应该不起作用的原因。
答案 3 :(得分:0)
一个选项可能是使您的导入线程持久化。即使线程完成导入,它也会进入空闲循环状态。这样,您的线程ManagedObjectContext将保留在正确的线程中。然后,当用户希望撤消更改时,向线程发送消息以使用undomanager。
答案 4 :(得分:0)
您很可能已经考虑过这一点,并且您可能只是在寻找使用现有undoManager
的解决方案,但以防万一:
由于您正在插入对象而不更新现有对象,因此您可以在导入每个批处理时使用事务ID标记它们,并在撤消时在后台线程中删除它们。对于标记,简单递增的NSNumber
就足够了。
不雅,但可行。