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

发布于 2024-09-10 23:34:12 字数 440 浏览 7 评论 0原文

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

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

有没有办法让我继续使用 Core Data 神奇的内置撤消支持,但又不会在此类重复的撤消记录上浪费宝贵的内存?我喜欢我不需要关心维护撤消/重做操作之间的对象图一致性,但无法正确处理这些连续的属性更新似乎是一个阻碍。

I have a Core Data based UIKit application that allows the user the drag objects around on the screen. While an object is being dragged, I update its position attribute on each touchesMoved: event. To support undoing a drag operation in one go, I start a new undo group at the beginning of the drag, and end the group when the user lifts their finger.

To save memory and to make undo operations fast, I want to coalesce undo data belonging to the drag operation, but Core Data makes this difficult. The problem is that processPendingChanges is called at the end of each run loop cycle, and it forces Core Data to file a new undo record for the position change that happened in that iteration. A drag operation can easily accumulate hundreds of such undo records, all of which but the first are unnecessary.

Is there a way for me to keep using Core Data's magical built-in undo support, but without wasting precious memory on such duplicate undo records? I love that I don't need to care about maintaining object graph consistency across undo/redo operations, but not being able to correctly handle these continuous attribute updates seems to be a showstopper.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苏大泽ㄣ 2024-09-17 23:34:12

我认为设置撤消管理器 setGroupsByEvent: 将执行您想要的操作。

设置一个布尔值,指定
是否自动接收
运行期间组撤消操作
环形。如果是,接收者创建
撤消每次遍历周围的组
运行循环;如果否,则不会。

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

I think setting the undo managers setGroupsByEvent: will do what you want.

Sets a Boolean value that specifies
whether the receiver automatically
groups undo operations during the run
loop. If YES, the receiver creates
undo groups around each pass through
the run loop; if NO it doesn’t.

A cleaner solution might be to simply not commit the objects position to the data model until the end of the drag event.

眼眸印温柔 2024-09-17 23:34:12

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

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

[moc processPendingChanges];
while ([moc.undoManager groupingLevel])
    [moc.undoManager endUndoGrouping];
[moc.undoManager disableUndoRegistration];

拖动手势完成后,您可以使用以下代码重新启用撤消注册:

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

此解决方案有效,但有点笨拙。 TechZen 建议的更简洁:在拖动手势完成之前不要更新模型属性。

One solution is to disable all undo registration after the very first drag event, and keep it disabled until the entire gesture is finished.

If you have groupsByEvent on, you'll need to keep in mind that the undo manager ignores all grouping messages while registration is off, including the one that ends the implicit group automatically at the end of the event. So if you plan to leave registration turned off at the end of the run loop, you'll have to manually close the implicit group yourself:

[moc processPendingChanges];
while ([moc.undoManager groupingLevel])
    [moc.undoManager endUndoGrouping];
[moc.undoManager disableUndoRegistration];

Once the drag gesture is finished, you can re-enable undo registration with the following code:

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

This solution works, but it is a bit kludgy. The one suggested by TechZen is much cleaner: don't update model attributes until the drag gesture is done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文