1

我有一个基于核心数据文档的应用程序,它通过与 NSManagedObjectContext 关联的内置 NSUndoManager 支持撤消/重做。我设置了一些动作,它们在 Core Data 中执行大量任务,通过beginUndoGrouping/将所有这些任务包装到一个撤消组endUndoGrouping中,并由 NSUndoManager 处理。

撤消工作正常。我可以执行几个连续的操作,然后依次撤消每一个操作,并且我的应用程序的状态得到正确维护。但是,永远不会启用“重做”菜单项。这意味着 NSUndoManager 告诉菜单没有要重做的项目。

我想知道为什么 NSUndoManager 似乎在撤消项目后会忘记它们,并且不允许重做?

我应该提到的一件事是,我在打开/创建文档后禁用撤消注册。当我执行一个动作时,我调用enableUndoRegistration, beginUndoGrouping,执行该动作,然后调用processPendingChanges, setActionName:, endUndoGrouping,最后调用disableUndoRegistration。这确保只有特定的操作是可撤消的,并且我在这些之外所做的任何其他数据更改都不会被 NSUndoManager 注意到。这可能是问题的一部分,但如果是这样,我想知道为什么它会影响重做?

提前致谢。

4

3 回答 3

3

实际上,只要在 -undo 和 -redo 之前调用 enableUndoRegistration (并在它们之后调用 disableUndoRegistration),就可以实现你想要的。

我相信您只是在更改托管对象之前和之后调用 enable(/disable)UndoRegistration 。这意味着您的“撤消”未在撤消管理器中注册,因此您无法“重做”它。

于 2010-05-08T14:21:43.857 回答
1

我已通过以下方式解决了此问题:

一直启用撤消注册,除了我明确不想记录撤消的时候。

我了解到:

如果在执行要记录的更改之前启用撤消注册,并在提交这些更改后立即禁用,则 NSUndoManager 的重做堆栈永远不会被填充。

所以,永远不要打电话disableUndoRegistration

于 2010-05-08T13:59:05.720 回答
1

我在启用“重做”的同时调用了 disableUndoManager。为此,我将 NSUndoManager 子类化并包含此方法:

-(void) undo
{
  [[appDelegate managedObjectContext] processPendingChanges];
  [self enableUndoRegistration];
  [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:[NSDate date]];
  [super undo];
  [[appDelegate managedObjectContext] processPendingChanges];
  [self disableUndoRegistration];
}

正如 Stefanf 在NSUndoManager、Core Data 和选择性撤消/重做中所述:“NSUndoManager 等待下一个运行循环周期,直到它注册您的更改”

于 2014-06-04T04:58:14.993 回答