我有一个基于Core Data文档的应用程序,它通过与NSManagedObjectContext关联的内置NSUndoManager支持撤消/重做。我设置了一些在Core Data中执行大量任务的操作,通过beginUndoGrouping
/ endUndoGrouping
将所有这些任务包装到撤消组中,并由NSUndoManager处理。
撤消工作正常。我可以执行几个连续的操作,然后逐个撤消它们中的每一个,并且我的应用程序的状态得到正确维护。但是,永远不会启用“重做”菜单项。这意味着NSUndoManager告诉菜单没有要重做的项目。
我想知道为什么NSUndoManager在撤消后似乎忘记了项目,并且不允许重做?
我应该提到的一件事是我在打开/创建文档后禁用撤消注册。当我执行操作时,我致电enableUndoRegistration
,beginUndoGrouping
,执行操作,然后致电processPendingChanges
,setActionName:
,endUndoGrouping
,最后致电{{1} }。这可以确保只有特定的操作是可撤消的,并且我在这些操作之外进行的任何其他数据更改都不会被注意到NSUndoManager。这可能是问题的一部分,但如果是这样,我想知道为什么它会影响重做?
提前致谢。
答案 0 :(得分:3)
实际上,只要你在-undo和-redo(以及之后的disableUndoRegistration)之前调用enableUndoRegistration,就可以实现你所追求的目标。
我相信您只是在对托管对象进行更改之前和之后调用启用(/禁用)UndoRegistration。这意味着您的“撤消”未在撤消管理器中注册,因此您无法“重做”它。
答案 1 :(得分:1)
我已通过以下方式解决了这个问题:
始终启用撤消注册,但我明确不想录制撤消的时间除外。
我已经了解到:
如果在执行要记录的更改之前启用撤消注册,并在提交这些更改后立即禁用,则NSUndoManager的重做堆栈永远不会被填充。
所以,永远不要打电话给disableUndoRegistration
。
答案 2 :(得分: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 and selective undo/redo中所述:“NSUndoManager等待下一个运行循环周期,直到它注册您的更改”