使用 CoreData 嵌套撤消组
我想将撤消管理器添加到 coredata 支持的 iPhone 应用程序中。当用户尝试添加新对象(通过点击 + 按钮)时,我加载一个新的模式视图控制器并在 viewDidLoad 中启动一个新的撤消组。
当用户按下“取消”按钮时,我想回滚 cancelAction 回调中的更改。
查询:
- 是否可以启动一个嵌套的撤消组并通过事件循环保留它并整理在一个撤消组中完成的所有更改?现在,当我在 cancelAction 中调用 beginUndoGrouping 时,我收到丢失的 beginUndoGrouping 异常。
- groupsByEvent API 对于 NSUndoManager 有什么意义?我是否需要将其设置为“否”才能通过事件循环保留撤消组?
- 在 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
}
I want to add a undo manager to a coredata backed iphone application. When the user tries to add a new object (by tapping on + button) I load a new modal viewcontroller and start a new undo group in viewDidLoad.
When the user presses Cancel button, I want to rollback the changes in cancelAction callback.
Queries:
- Is it possible to start a nested Undo group and persist it through event loop and collate all the changes done in one single undo group? Right now, when I call beginUndoGrouping in cancelAction, I get a missing beginUndoGrouping exception.
- What is the significance of groupsByEvent API for NSUndoManager? Do I require to set it to NO to persist an undo group through event loop?
- What needs to be done in saveAction callback to make changes permanent (apart from calling save on mangedObjectContext)? How do I tell Undo Manager to stop tracking the changes?
Error Message:
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '_endUndoGroupRemovingIfEmpty:: NSUndoManager 0x75415f0 is in invalid state, endUndoGrouping called with no matching begin
Sample Code:
// 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
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从您的具体问题开始 - 是的,您可以使用 beginUndoGrouping 和 endUndoGrouping 手动定义撤消操作的范围。
在这种情况下,无论是否设置 groupsByEvent,撤消操作都应该有效。这是因为事件循环生成的所有撤消组都嵌套在以 beginUndoGrouping 开始的主打开撤消分组下,并且只要在调用 endUndoGrouping 后直接调用 undoNestedGroup 就应该可以工作。如果您不使用事件循环撤消分组,请不要担心并将其设置为“否”。
要使更改永久化,请使用 endUndoGrouping 关闭撤消组并在上下文中调用 save。不需要 processPendingChanges 调用,并且可能会导致嵌套组出现问题。如果您想清除撤消操作,请在 endUndoGrouping 之后在撤消管理器上调用removeAllActions - 这保证了更改永远不会被撤消。
使用断点/nslog 确保您的开始/结束调用是一一对应的。
如果您希望取消操作类似于“撤消按钮”,则必须执行以下操作:
将 beginUndoGrouping 移动到 viewWillAppear
在 viewWillDisappear 中调用 endUndoGrouping
在取消操作结束时重新打开撤消分组
在保存操作结束时重新打开撤消分组
否则,如果您保持原样,请确保在保存和取消操作中关闭对话框,以避免多次调用 endUndoGrouping 的可能性。
如果有任何疑问,请评论,我会更新。
祝你好运!
Beginning with your specific questions - Yes, you can manually define the bounds of an undo operation using beginUndoGrouping and endUndoGrouping.
In this case, the undo operation should work whether or not groupsByEvent is set. This is because all the undo groups that are generated by the event loop are nested under your main open undo grouping started with beginUndoGrouping, and as long as you call undoNestedGroup directly after you call endUndoGrouping, it should work. If you are not using the event loop undo groupings, don't worry about it and set it to NO.
To make your changes permanent, close the undo group with endUndoGrouping and call save on your context. The processPendingChanges calls are not needed, and may cause issues in nested groups. If you want clear the undo operations, call removeAllActions on your undomanager after endUndoGrouping - this guarantees the changes will never be un-did.
Use breakpoints/nslog to make sure your begin/end calls are one for one.
If you want your cancel action to be like an 'undo button', you'll have to do the following:
Move beginUndoGrouping to viewWillAppear
Call endUndoGrouping in viewWillDisappear
re-open undo grouping at the end of your cancel action
re-open undo grouping at the end of your save action
Otherwise, if you leave it as is, make sure you close the dialog in your save and cancel actions, to avoid possibility of endUndoGrouping being called multiple times.
If you have any questions, please comment and I'll update.
Good luck!