CoreData使用NSUndoManager抛出异常

时间:2012-07-25 20:48:47

标签: ios core-data nsundomanager

我有一个iPad应用程序,我正在使用带有核心数据的NSUndoManager。事情通常很有效,除了当我多次撤消/重做时有一个半可重复的错误。我只在主线程上工作(至少,我已禁用MagicalRecords在辅助线程上使用NSManagedObject。如果我尝试撤消/重做NSManagedObject到上下文的插入,则会出现问题。

所以我有这样的事情:

if (!self.undoManager.isUndoing && !self.undoManager.isRedoing) 
{
    [self.undoManager undo];   
}
else 
{
    NSLog(@"gotcha!");
}

经过几次,我得到以下异常。它发生在辅助线程上,这让我觉得Core Data正在后台做一些事情。

CoreData: error: Serious application error.  Exception was caught during Core Data
change processing.  This is usually a bug within an observer of 
NSManagedObjectContextObjectsDidChangeNotification.  _registerUndoObject:: NSUndoManager 
0xcea2d60 is in invalid state, must begin a group before registering undo
with userInfo (null) 2012-07-25 15:42:26.850 TT[3972:3c07] *** Terminating app due to 
uncaught exception 'NSInternalInconsistencyException', reason: '_registerUndoObject::
NSUndoManager 0xcea2d60 is in invalid state, must begin a group before registering undo

有时我也会获得EXEC_BAD_ACCESS,有时候只是上面的例外。

知道可能导致这种情况的原因吗?

编辑:Mundi的澄清情况(见评论)

2 个答案:

答案 0 :(得分:0)

撤消托管对象插入的标准方法是

[self.managedObjectContext deleteObject:theManagedObject];
// If you have saved already, you would need to save again.

无需使用撤消机制。像这样,您的代码变为

  • 更具可读性(您明确说明了您想要做的事情)和
  • 不易出错(没有更复杂的API的无法预料的事件)。

答案 1 :(得分:0)

这是阻止我所有崩溃的解决方案: 显然,Magical Records默认使用privateQueue并发,如果你的代码不是那么线程安全的话,我想事情就不行了。我所做的是将NSPrivateQueueConcurrencyType更改为NSMainQueueConcurrencyType以获取以下方法:

+ (NSManagedObjectContext *) MR_contextWithoutParent;
{
    NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
return context;
}

我还发现了另一个在这里工作的细节: Core Data deleteObject: sets attributes to nil

我需要做的是在添加/删除托管对象之前保存托管对象上下文。有点奇怪和低效,但节省了很多麻烦。