我有两个NSManagedObjectContext
实例:一个在主线程中使用,另一个在后台线程中使用(通过NSOperation
。)为了线程安全,这两个上下文只共享一个{ {1}}。
我遇到的问题是第一个上下文(主线程)上的挂起更改在第二个上下文不可用,直到执行NSPersistentStoreCoordinator
。这是可以理解的,因为共享持久性存储不会保留由-save
,NSManagedObjects
和-insertedObjects
跟踪的-updatedObjects
的副本。
不幸的是,这会给用户体验带来问题:任何未保存的更改都不会出现在后台线程中生成的(耗时)报告中。
我能想到的唯一解决方案是讨厌的:从第一个上下文中取出插入的,更新的和删除的对象,并将它们移植到第二个上下文的对象图上。数据集中有一些非常复杂的关系,所以我对这个方向犹豫不决。我希望有人在这里作为更好的解决方案。
答案 0 :(得分:4)
如果这是10.7以下有一些解决方案:一个是你可以拥有嵌套的ManagedObjectContexts,所以你可以“保存”在被修改的那个中,它不会一直保存到磁盘,但它会使主要上下文的其他子级可用的更改。
在10.7之前,您可能需要自己复制更改。这不是非常难的,因为您可以只有一个对象侦听NSManagedObjectContextObjectsDidChangeNotification
,然后只是从主要上下文中重新应用更改。 (应该是大约20行代码。)你永远不必保存我假设的第二个上下文?
答案 1 :(得分:2)
不确定您是否有任何操作系统限制,但在iOS 5 / Mac OS 10.7中,您可以使用嵌套的托管对象上下文来完成此操作。我相信子上下文能够通过简单地执行新的提取来提取父级中未保存的更改。
编辑:看起来Wil打败了我,但是,在iOS 5 / Mac OS 10.7之前,您必须先监听NSManagedObjectContextDidSaveNotification并查看添加的userInfo字典/更新/删除的对象。
答案 2 :(得分:0)
备用解决方案可能涉及使用单个托管对象上下文并提供自己的线程安全性来访问它,或使用上下文的锁定和解锁方法。
答案 3 :(得分:0)
我会尝试让主线程执行正常保存,因此第二个上下文可以将更改合并到其上下文中。 “打击”API预期用途绝不是一个好主意。 您可以使用属性作为中间标记新保存的记录,如果用户最终取消编辑,则稍后删除。
使用实体中的属性解决这些问题,并使用匹配的谓词在后台线程中查询将很容易...
这也是一个稳定的解决方案。我来自数据库驱动的世界(oracle)我们经常使用这样的模式(记录中的状态属性)使数据对其他数据库会话可见/不可见(这等于cocoa应用程序中的线程)。工作总是没有问题。其他线程/会话总是只看到提交的更改,这是大多数RDBMS的工作方式。