Core data 跨多个运行循环周期的操作的核心数据撤消合并

Core data 跨多个运行循环周期的操作的核心数据撤消合并,core-data,undo,nsundomanager,Core Data,Undo,Nsundomanager,我有一个基于核心数据的UIKit应用程序,允许用户在屏幕上拖动对象。拖动对象时,我会在每个touchesMoved:事件上更新其位置属性。为了支持一次性撤消拖动操作,我在拖动开始时启动一个新的撤消组,并在用户抬起手指时结束该组 为了节省内存并加快撤消操作,我想合并属于拖动操作的撤消数据,但核心数据使这变得很困难。问题是在每个运行循环周期结束时调用processPendingChanges,它强制核心数据为该迭代中发生的位置更改提交新的撤消记录。拖动操作可以轻松累积数百条此类撤消记录,除第一条记录

我有一个基于核心数据的UIKit应用程序,允许用户在屏幕上拖动对象。拖动对象时,我会在每个
touchesMoved:
事件上更新其位置属性。为了支持一次性撤消拖动操作,我在拖动开始时启动一个新的撤消组,并在用户抬起手指时结束该组

为了节省内存并加快撤消操作,我想合并属于拖动操作的撤消数据,但核心数据使这变得很困难。问题是在每个运行循环周期结束时调用
processPendingChanges
,它强制核心数据为该迭代中发生的位置更改提交新的撤消记录。拖动操作可以轻松累积数百条此类撤消记录,除第一条记录外,所有记录都是不必要的


有没有一种方法可以让我继续使用Core Data神奇的内置撤销支持,但又不会在这些重复的撤销记录上浪费宝贵的内存?我喜欢我不需要关心在撤销/重做操作中保持对象图的一致性,但不能正确处理这些连续的属性更新似乎是一个障碍。

我认为设置撤销管理器
setGroupsByEvent:
可以满足您的需要

设置一个布尔值,该值指定 接收器是否自动关闭 组在运行期间撤消操作 环如果是,则接收器创建 撤消每个通道周围的组 运行循环;如果不是的话


一个更简洁的解决方案可能是在拖动事件结束之前不将对象位置提交到数据模型

一种解决方案是在第一次拖动事件后禁用所有撤消注册,并保持禁用状态,直到整个手势完成

如果启用了
groupsByEvent
,则需要记住,撤消管理器会在注册关闭时忽略所有分组消息,包括在事件结束时自动结束隐式组的消息。因此,如果计划在运行循环结束时关闭注册,则必须自己手动关闭隐式组:

[moc processPendingChanges];
while ([moc.undoManager groupingLevel])
    [moc.undoManager endUndoGrouping];
[moc.undoManager disableUndoRegistration];
完成拖动手势后,可以使用以下代码重新启用撤消注册:

[moc processPendingChanges];
[moc.undoManager enableUndoRegistration];

这个解决方案可行,但有点笨拙。TechZen建议的方法更简洁:在完成拖动动作之前不要更新模型属性。

遗憾的是
setGroupsByEvent:
在这里没有帮助。拖动跨越多个事件,因此除非我误解了一些基本内容,否则无法使用
beginUndoGrouping
/
endUndoGrouping
-明确地将我的更改分组,
setGroupsByEvent
在已经有一个打开的组时变为不可操作。在拖动手势结束之前不更改模型可能是最好的方法。问题是我没有地方存储瞬态位置-我直接从模型进行渲染,没有单独的视图对象。但也许这只是意味着现在是时候添加它们了!IIRC,将
groupsByEvent
设置为
NO
,您将得到一个超出运行循环的长撤消组。不,将
groupsByEvent
设置为
NO
只会禁用隐式分组,因此您需要始终启动和结束您自己的组。是的,您自己创建的组显然可以超越单个运行循环迭代。这不是问题所在。问题是每次运行循环迭代结束时自动调用
performPendingChanges
,导致内存使用和性能问题。您建议的更简洁的解决方案恰好是一个很好的解决方案:如果模型仅在手势结束时更改,
performPendingChanges
不会在每次运行循环迭代中注册新的撤消操作。好的,我已经有一段时间没有摆弄它了。事实证明,更干净的方法并不适合我的应用程序——系统地引入一个单独的(可独立调整的)视图树与我的模型对象并行会带来太多的复杂性。我最终使用了这个更简单的解决方案。