我有一个基于Cocoa文档的应用程序,即使我拥有Core Data负责所有这些工作,也遇到了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]];


之所以这样做,是因为我遇到了类似的问题,如下所述:
Enable saving of document NSManagedObjectContext immediately?

我之所以提出这一点,是因为这是我的应用程序中甚至触摸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] beginUndoGrouping],但是问题是我的程序中没有使用“ [[context undoManager] endUndoGrouping]”的地方。以前有没有人经历过?

任何帮助表示赞赏。

最佳答案

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

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

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

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

09-19 21:36