使用 2 个链接的 ManagedObjectContext 应用程序撤消 CoreData 更改
Posted
技术标签:
【中文标题】使用 2 个链接的 ManagedObjectContext 应用程序撤消 CoreData 更改【英文标题】:Undo CoreData changes with 2 chained ManagedObjectContext application 【发布时间】:2014-02-09 10:08:54 【问题描述】:我正在开发一个应用程序,用户可以手动编辑一些条目,但它们也可以从服务器更新。
对于用户更新,我使用 UndoManager 来允许用户取消/确认更改组。当用户进入编辑模式时,我正在做:
//when edit mode is entered
[[self.contact.managedObjectContext undoManager] beginUndoGrouping];
//when edit mode is finished
[[self.contact.managedObjectContext undoManager] endUndoGrouping];
//depending on button that was pressed to end edit mode, either:
[[self.contact.managedObjectContext undoManager] undo];
//or
[[self.contact managedObjectContext] save:nil];
对于来自服务器的自动更新(对象可以由服务器更改),我使用的是子父 MOC。我用来管理编辑模式的上面那个是父模式。我正在创建一个子 MOC,并在后台从服务器拉取更改。在我正在做的过程结束时:
[self.moc.save:nil]; //save to local MOC
[self.moc.parentContext.save:nil]; //save to main thread MOC (the one with undo)
我的问题是,目前如果在用户编辑时发生更改并且用户决定执行 UNDO - 所有自动拉出的更改也会丢失。
作为我想到的解决方法:
-
当用户处于编辑模式时阻止自动更新
进行自动更新时阻止编辑模式
但这听起来需要大量的工作和潜在的错误。也许有一种方法可以解决我在 MOC 层上的问题,因此可以将用户操作与自动保存分开。
【问题讨论】:
这有帮助吗:***.com/questions/13898472/… ? Martin R.Thanks 会试一试 - 在提问之前没有发现,但看起来很有希望。 【参考方案1】:我不知道您是否只是偷工减料,但您需要小心保存上下文的位置。确保在正确的线程上执行此操作。
我猜你有一个私有队列子队列和一个主队列父队列。使用 performBlock... 依次保存。
正如其他人所指出的,在保存子项时,您应该取消注册主撤消管理器,以防止它为子项的更改生成撤消。
与撤消管理器合并可能会变得非常混乱,并导致删除对象等丑陋的问题。我通常只是在安全方面犯错,并在与removeAllActions
合并后完全清除撤消管理器。
【讨论】:
感谢您的指出。我无法删除所有撤消操作,我需要编辑模式才能撤消,但我已经设法使其与 disableUndoRegistration 一起工作。我现在还有其他问题,但它来自我的合并逻辑。使用集中式上下文管理代码,我不觉得它太乱。【参考方案2】:你的事情有点混乱。
对于您希望原子更新的用户更新,请使用父子上下文。优点是如有必要,可以丢弃对子上下文所做的任何更改,例如如果点击取消。两者显然都是主要的队列上下文。永远不要在后台使用子上下文(即使用私有队列),它们不是为此而设计的,如果你这样做只会让你的主线程在保存将多个更改合并到主线程上下文时挂起更长的时间。
对于您的后台服务器更新,您应该使用带有新持久存储协调器的私有队列上下文或使用方便的方法persistentContainer.newBackgroundContext
。请参阅 Apple 的 Earthquakes 示例。
【讨论】:
以上是关于使用 2 个链接的 ManagedObjectContext 应用程序撤消 CoreData 更改的主要内容,如果未能解决你的问题,请参考以下文章