带有CoreData的嵌套撤消组

sia*_*asl 6 iphone core-data nsundomanager

我想在一个coredata支持的iphone应用程序中添加一个撤消管理器.当用户尝试添加新对象时(通过点击+按钮),我加载一个新的模态视图控制器并在viewDidLoad中启动一个新的撤消组.

当用户按下取消按钮时,我想回滚cancelAction回调中的更改.

查询:

  1. 是否可以启动嵌套的撤消组并通过事件循环将其保留并整理在一个撤消组中完成的所有更改?现在,当我在cancelAction中调用beginUndoGrouping时,我得到一个缺少的beginUndoGrouping异常.
  2. groupsByEvent API对NSUndoManager的意义是什么?我是否需要将其设置为NO才能通过事件循环保留撤消组?
  3. 在saveAction回调中需要做什么才能永久更改(除了在mangedObjectContext上调用save)?如何告知撤消管理器停止跟踪更改?

错误信息:

*由于未捕获的异常'NSInternalInconsistencyException'终止应用程序,原因:'_endUndoGroupRemovingIfEmpty :: NSUndoManager 0x75415f0处于无效状态,调用endUndoGrouping时没有匹配的开始

示例代码:

// RootViewController.m
- (void) addAction {
   // Load Modal View Controller to add new object

}

// AddViewController.m
- (void) viewDidLoad {
   // Start nested undo group
   [self.managedObjectContext processPendingChanges];
   [self.managedObjectContext.undoManager beginUndoGrouping];

   [self createModel];

}

- (void) cancelAction {
    // Revert all changes
    [self.managedObjectContext processPendingChanges];
    [self.managedObjectContext.undoManager endUndoGrouping];

    [self.managedObjectContext.undoManager undoNestedGroup];

    ...
}

- (void) saveAction {

    // Save changes
}
Run Code Online (Sandbox Code Playgroud)

Jac*_*ngs 7

从您的具体问题开始 - 是的,您可以使用beginUndoGrouping和endUndoGrouping手动定义撤消操作的范围.

在这种情况下,无论是否设置了groupsByEvent,撤消操作都应该起作用.这是因为事件循环生成的所有撤消组都嵌套在以beginUndoGrouping开头的主要开放撤消分组下,并且只要在调用endUndoGrouping之后直接调用undoNestedGroup,它就应该有效.如果您没有使用事件循环撤消分组,请不要担心并将其设置为NO.

要使更改成为永久更改,请使用endUndoGrouping关闭撤消组,并在上下文中调用save.不需要processPendingChanges调用,并且可能会导致嵌套组出现问题.如果要清除撤消操作,请在endUndoGrouping之后调用undomanager上的removeAllActions - 这可以保证更改永远不会取消.

使用breakpoints/nslog确保您的开始/结束调用是一对一的.

如果您希望取消操作就像"撤消按钮",则必须执行以下操作:

  • 将beginUndoGrouping移动到viewWillAppear

  • 在viewWillDisappear中调用endUndoGrouping

  • 在取消操作结束时重新打开撤消分组

  • 在保存操作结束时重新打开撤消分组

否则,如果保持原样,请确保在保存和取消操作中关闭对话框,以避免多次调用endUndoGrouping.

如果您有任何疑问,请发表评论,我会更新.

祝好运!