一一保存 NSUndoManager 事务

Posted

技术标签:

【中文标题】一一保存 NSUndoManager 事务【英文标题】:Save NSUndoManager transactions one by one 【发布时间】:2015-05-28 22:32:15 【问题描述】:

我不仅需要将更改保存到本地Core Data,还需要保存在服务器上。

我担心的是,在我的情况下,用户可以在短时间内进行大量交互。在交互之间没有足够的时间来接收从服务器返回的成功消息。因此,要么我锁定 GUI,直到下一条消息返回 - 现在就是这种情况 - 要么选择不同的方法。

我的新方法是让用户进行许多交互并将事务放在NSUndoManager 提供的undo stack 上,在NSManagedObjectContext 上启用,但只保存/提交收到成功消息的事务。如何一次移动一个撤消“光标”,一一提交记录,尽管上下文已经包含大量未保存的更改?

【问题讨论】:

【参考方案1】:

NSUndoManager 并不真正适合这项任务。您可以告诉它撤消或重做操作,但您不能检查这些操作或有选择地将数据保存在当前撤消堆栈中。

我过去所做的是创建自己的传出更改队列。每当更改保存在本地时,将这些更改添加到未同步的传出更改列表中。然后使用不同的队列通过将队列发送到服务器来处理该队列,如果服务器报告成功,则清除这些更改。您可以使用NSManagedObjectContextWillSaveNotification 和/或NSManagedObjectContextDidSaveNotification 来监控更改并更新出站队列。

这意味着 ios 设备可能已将服务器不知道的更改排队,尤其是在网络不可靠或不可用的情况下。不过,在这些情况下,这几乎是不可避免的,除非你做了一些糟糕的事情,比如在网络恢复正常之前拒绝让人们进行新的更改。

【讨论】:

像你的方法一样,最后我选择了一个不同的,两个独立的 MOC,PSC,甚至 sqlite,所有的变化都进入了两者,但是 'main' 尽快写入,'writer' 收到成功消息时,通常它们都包含相同的,仅在 GUI 中使用“main”,如果出现问题,客户端用“writer”sqlite 覆盖“main”sqlite,重新加载“main”PSC、MOC 和相关 FRC-s,它会发生很少,你怎么看? 听起来很可能会导致应用崩溃和数据丢失。如果有任何事情导致您的应用程序在等待“成功”时退出,那么您的“编写器”数据将过期,因为从未保存更改。如果您将其复制到“main”,则该数据将丢失。此外,在复制数据时,如果您的应用程序保留对与“主”堆栈相关的任何对象的任何引用,您几乎肯定会崩溃。您必须在应用程序中重新加载任何类型的 Core Data 对象以避免麻烦。 我觉得我们的区别,如果网络出了问题,我做一个回滚,忘记拒绝交互,回到上一个稳定状态,用户会明白情况,他可以重试。当网络恢复时,您会跟踪更改并尝试重新发送更改?!我认为如果应用程序不发送超级敏感数据,只按一次发送是很重要的,那么我的方法是可以的。

以上是关于一一保存 NSUndoManager 事务的主要内容,如果未能解决你的问题,请参考以下文章

MySQL事务中的redo与undo

redo日志undo日志与事务隔离性

分布式事务和mysql中undo和redo日志

事务--04---MySQL事务日志----Undo日志

数据库事务系列3 undo

day05