是否可以将多个NSUndoManagers与一个Core-Data managedObjectContext一起使用?

时间:2011-02-12 21:04:18

标签: iphone core-data nsundomanager

//编辑:真的,没有人对此有任何建议或想法?我是不是错误地问了这个问题?//

我的iPhone应用程序有一个带有中等复杂数据模型的managedObjectContext。我现在正在添加撤消功能,并不清楚如何最好地处理嵌套的viewControllers(因为每个层可能会修改数据模型)。

  

Apple的文档指出:   “考虑显示的应用程序   书籍清单,并允许您   然后导航到详细视图   允许您编辑个人   书的属性(如它的   标题,作者和版权日期)。   你可以从中创建一本新书   列表屏幕,在两个之间导航   其他屏幕编辑其属性,   然后导航回原始版本   名单。如果一个,它可能看起来很奇怪   撤消列表视图中的操作   对作者姓名的更改   两个屏幕而不是   删除整本书。“


那么实现这个的最佳方法是什么?目前,我正在考虑让每个viewController保留自己的undoManager,只要它在屏幕上,它就会处于活动状态。所以我的理解是,这将需要以下步骤(对于每个VC):

  • 添加媒体资源:myUndoManager
  • 添加undoManager方法,返回myManagedObjectContext.undoManager;
  • viewDidAppearmyManagedObjectContext.undoManager = myUndoManager; //首先创建if nil
  • viewWillDisappearmyManagedObjectContext.undoManager = nil;
  • 内存警告:[self.undoManager removeAllActions ];
  • 关于dealloc:self.myUndoManager = nil;
  • 对于每个模型更改:[self.undoManager setActionName:NSLocalizedString(@“XXX”,@“”)];
  • CoreData将处理实际的撤消/重做帖子

另外,我必须保持第一个响应者:

  • viewDidAppear:`[self becomeFirstResponder]'
  • 添加canBecomeFirstResponder方法,返回YES
  • viewWillDisappear:[self resignFirstResponder];
  • 在子视图重新签名时重新启用firstResponder(例如textFields)

到目前为止,这似乎是有效的,即使在加载/卸载周期中也是如此,而且非常自包含,但我有几个问题:

  • 首先,这是跨多个VC实施撤消的最佳做法吗?
  • 在我做早期的活动之前,我的孩子VC会不会做他们的工作吗?
  • 如果是的话,该列表是否会捕获我需要做的所有事情?
  • ManagedObjectContext是否会与多个正在运行的UndoManagers混淆?
  • 在交换undoManagers之前,是否需要调用ProcessPendingActions?

3 个答案:

答案 0 :(得分:1)

我会非常努力地只有一个撤消管理器。
考虑一下情景:

型号:(鸡)
特性:鸡蛋,颜色,大小;

型号:(鸡蛋)
属性:鸡肉,颜色;

chicken.eggs =与蛋有一对多的关系,对egg.chicken是正确的。

为chickenViewController创建一个撤消管理器,为eggViewController创建一个撤消管理器 你创造了chicken0及其鸡蛋:egg0,egg1 你创造了chicken1及其鸡蛋:egg2,egg3 你删除egg2。

现在你删除chicken1级联删除鸡蛋 现在你回到eggViewController并撤消...你想要发生什么(例外情况会发生) 现在你撤消了chickenViewController和chicken1它的鸡蛋回来了,但是有2个egg2的吗?

修改 我在这一点上软化了我的语气, 假设您正在使用分层视图结构,如UINavigationController,并且每次进入子视图时都会创建一个新的Undo控制器,我不应该遇到问题。

答案 1 :(得分:0)

听起来你想把一堆undos变成一个整体,这样他们就可以像一个团队一样完成任务。这是通过beginUndoGrouping和endUndoGrouping完成的。你有什么理由不能使用它吗?我不确定你是否可以在组中间撤消一步,这将是一个问题。

答案 2 :(得分:0)

每个视图控制器都可以拥有自己的撤消管理器。控制器应该只负责它直接更改的字段。退出相应的视图后,应该释放控制器并使用它来撤消管理器。

假设您有3个级别。级别1表示整个记录,级别2表示级别1的数据子集,级别3表示级别2的数据子集。

退出第3级后,您基本上已经说过我接受,您不需要撤消第2级中的任何数据。此更改的数据应仅显示为已读 - 如果完全显示,则仅为第2级中的数据。同样,一旦退出第2级,您应该释放其撤消管理器。

回到第1级,因为它代表整个记录,为什么没有取消按钮而不是试图撤消(或者除了你的等级1控制器做什么之外)?

然后,如果要取消整个操作,可以向管理对象上下文发送如下消息:

[myMOC refreshObject:theEditedObject mergeChanges:NO];

这将有效地回滚整个记录

如果出于某种原因,当你处于第2级并且在第2级进行回滚时,你决定保留第3级的撤消管理器,那么只会回滚与第2级撤消管理器有关的数据。级别3的撤消管理器是独立的,核心数据不会将撤消管理器视为嵌套。

由于多个撤消管理器,托管对象上下文不会混淆,因为它只能通过setUndoManager:方法一次跟踪一个。

您可能不需要使用processPendingChanges,除非在更改完成之后以某种方式在事件循环完成之前发生回滚。我不担心这个,除非你的撤销只恢复一些应该用撤销管理器记录的数据。