Objective c NSUndoManager+;调用endUndoGrouping时没有匹配的开始

Objective c NSUndoManager+;调用endUndoGrouping时没有匹配的开始,objective-c,cocoa,core-data,nsundomanager,Objective C,Cocoa,Core Data,Nsundomanager,我有一个基于Cocoa文档的应用程序,在使用NSUndoManager时遇到了一些问题,尽管我让核心数据来处理所有这些问题 因此,每次创建新的持久性文档时,我都会创建一个根上下文和一个子上下文。根上下文负责写入持久文档,子上下文是我通过创建/编辑/删除NSManagedObjects修改的上下文。我将根上下文设置为父上下文。我还将子上下文的撤消管理器设置为使用NSPersistentDocument创建的原始上下文。下面是一些代码,希望能让它更清晰一些: // create root conte

我有一个基于Cocoa文档的应用程序,在使用NSUndoManager时遇到了一些问题,尽管我让核心数据来处理所有这些问题

因此,每次创建新的持久性文档时,我都会创建一个根上下文和一个子上下文。根上下文负责写入持久文档,子上下文是我通过创建/编辑/删除NSManagedObjects修改的上下文。我将根上下文设置为父上下文。我还将子上下文的撤消管理器设置为使用NSPersistentDocument创建的原始上下文。下面是一些代码,希望能让它更清晰一些:

// create root context
NSManagedObjectContext *rootContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

// startContext is the context created with the document
[rootContext setPersistentStoreCoordinator:[startContext persistentStoreCoordinator]];
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

// set root as parent
[childContext setParentContext:rootContext];

// set undo
[childContext setUndoManager:[startContext undoManager]];
我之所以这么做,是因为我遇到了类似的问题,如下所述:

所以我提出这个问题,因为这是我应用程序中唯一一个我甚至可以触摸NSUndoManager的代码。我正在测试我的应用程序,只需插入NSManagedObjects,然后撤消插入。有时在两次、五次、甚至十次撤销后,我会收到以下错误:

_endUndoGroupRemovingIfEmpty:: NSUndoManager 0x100159f30 is in invalid state,   endUndoGrouping called with no matching begin
2013-01-29 21:31:23.375 TestApplication[30125:303] (
0   CoreFoundation                      0x00007fff8a54f0a6 __exceptionPreprocess + 198
1   libobjc.A.dylib                     0x00007fff8215f3f0 objc_exception_throw + 43
2   CoreFoundation                      0x00007fff8a54ee7c +[NSException raise:format:] + 204
3   Foundation                          0x00007fff80ea021f -[NSUndoManager _endUndoGroupRemovingIfEmpty:] + 195
4   Foundation                          0x00007fff80ea0154 -[NSUndoManager endUndoGrouping] + 42
5   Foundation                          0x00007fff80ed79da +[NSUndoManager(NSPrivate) _endTopLevelGroupings] + 447
6   AppKit                              0x00007fff8253632d -[NSApplication run] + 687
7   AppKit                              0x00007fff824dacb6 NSApplicationMain + 869
8   TestApplication                     0x0000000100001512 main + 34
9   TestApplication                     0x00000001000014e4 start + 52
因此,如果我正确地读取了调试信息,那么我需要调用
[[context undoManager]beginundogrouting]
,但是问题是,在我的程序中没有地方使用“[[context undoManager]endundogrouting]”。以前有人经历过吗


非常感谢您的帮助。

OSX中的每个上下文默认情况下都会创建一个undoManager(iOS中为零)。分组错误的原因是您的子上下文undoManager试图将更改嵌套在根上下文的undoManager中,该undoManager嵌套在startContext undoManager中(与子上下文的undoManager相同)


对我来说,这似乎是由于在撤消/重做处理期间发送begin/endGrouping消息造成的。 我暂时禁用撤消注册以删除此错误消息

    [[NSNotificationCenter defaultCenter] addObserverForName:NSUndoManagerDidUndoChangeNotification object:undoManager queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {

            [undoManager disableUndoRegistration];

            // Some code for undo containing undo grouping

            [undoManager enableUndoRegistration];

    }
我又挖了一些,发现了这个。
在我的项目中,一些排序操作是在后台线程上运行的子托管对象上下文中完成的,我尝试撤消整个过程,包括主线程(顶级上下文)中的排序操作。我可以通过将排序操作移动到后台线程来解决这个问题,就像在撤消/重做期间一样。

wow!这对我来说毫无意义,我从来没有想到过这一点。谢谢,果味!我最初的想法是错误的。在OSX中,MOC默认创建undoManager,在iOS中默认为零。但实际上,孩子会在保存时向家长注册更改。观察相同的通知时会出现相同的错误。
    [[NSNotificationCenter defaultCenter] addObserverForName:NSUndoManagerDidUndoChangeNotification object:undoManager queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {

            [undoManager disableUndoRegistration];

            // Some code for undo containing undo grouping

            [undoManager enableUndoRegistration];

    }