mergeChangesFromContextDidSaveNotification 后 CoreData 关系为零
iOS 上的 Core Data 有一些非常奇怪的行为。
我的主线程有一个 NSManagedObjectContext ,用于从 SQLLite 持久存储中读取数据并将其显示给用户。我还有由 NSOperationQueue 管理的后台进程。这些后台进程创建一个 NSMangedObjectContext,从远程服务器获取数据,并将该数据保存到本地核心数据存储中。
我已经注册了 NSManagedObjectContextDidSaveNotification
,当我收到这些通知时,我在主线程的 NSManagedObjectContext
上调用 mergeChangesFromContextDidSaveNotification
(将通知对象作为参数传递)。
这都是非常标准的,也是所有核心数据文档建议您处理多线程的方式。
直到最近,我一直将新对象插入数据存储中,而不是修改数据存储中的对象。这很好用。后台线程写入新数据后,发生合并,我向 UIController 发送通知并重新绘制显示。显示器绘制正确。
最近我做了一个改变,后台线程既在插入又在修改对象。但该模式的其余部分保持不变。现在,合并后,我的主线程的 NSManagedObjectContext 中的数据已损坏。如果我尝试查询对象,我什么也得不到。如果我尝试检查我已经引用的对象,那么它们的所有关系都是零(不是错误而是零)。我检查了SQLLite数据库,数据都在那里。
唯一的解决方案似乎是重置 NSManagedObjectContext ,考虑到应用程序的架构,这是不可接受的。
好吧,最后一点奇怪的地方。如果我的后台线程仅更新属性(基元),那么我不会得到这种奇怪的行为。但是,如果我更新关系本身,那么我会得到这些空的获取请求结果并且将关系清零。
我缺少什么?
Having some truly strange behavior with Core Data on iOS.
I have a NSManagedObjectContext
for my main thread used to read data from a SQLLite persistent store and display it to the user. I also have background processes managed by an NSOperationQueue
. These background processes create an NSMangedObjectContext
, fetch data from remote servers, and persist that data to the local Core Data store.
I have registered for NSManagedObjectContextDidSaveNotification
and when I receive those notifications I call mergeChangesFromContextDidSaveNotification
on the main thread's NSManagedObjectContext
(passing the notification object as an argument).
This is all very standard and the way that all the Core Data document suggest that you deal with multi-threading.
Up until recently, I have always been inserting new objects into the data store and not modifying objects in the data store. This worked fine. After a background thread writes new data, the merge occurs, I send a notification to the UIController and redraw my display. The display draws correctly.
Recently I have made a change, and the background thread is both inserting and modifying objects. But all the rest of the pattern remains the same. Now after the merge, the data in my main thread’s NSManagedObjectContext
is corrupted. If I try to query for objects, I get nothing back. If I try to examine objects which I already have a reference to all their relationships are nil (not faults but nil). I have checked the SQLLite database and the data is all there.
The only solution seems to be to reset the NSManagedObjectContext
which isn’t acceptable given the architecture of the applicaiton.
Ok, a final bit of strangeness. If my background thread is only updating attributes (primitves) then I don’t get this strange behavior. However, if I update the relationships themselves, then I get these empty fetch request results and nil’d out relationships.
What am I missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,我找到了我的问题。
我的问题是
mergeChangesFromContextDidSaveNotification
将更改从一个线程合并到另一个线程的方式。正如我多次阅读的那样,它不会回放您所做的更改,而是将最终状态合并在一起。我没有意识到这的后果。在我的后台线程中,我正在删除一个对象,但在删除它之前,我清空了它的一些关系,因为它们被标记为级联删除,我不希望它们被删除。显然,当我将这些已删除的对象合并到主上下文中时,Core Data 仍然强制执行删除规则,并级联删除主上下文中的相关对象。
我更改了删除规则,现在我的关系不会被错误地清零。不幸的是,我有一种关系,在某些情况下我希望删除级联,而在其他情况下我则不想。我必须为此努力。
Ok, I figured out my problem.
My problem is the way that
mergeChangesFromContextDidSaveNotification
merges changes from one thread to another. As I have read several times, it does not do a playback of the changes you made but rather merges the final state together. I didn't realize the ramifications of this. In my background thread, I am deleting an object, but before I delete it I nil out some of its relationships because they are marked as cascade delete and I don't want them deleted.Apparently when I merge those deleted objects into the main context, Core Data still enforces the delete rules and cascade deletes the related objects in the main context.
I changed my delete rules and now my relationships is not getting incorrectly nil'd out. It is unfortunate that I have a relationship which in some cases I want cascade deleted and in others I don't. I will have to work on that.