Reputation: 33050
How to update child managed object context so it has the same data with parent?
As far as I know, when saving, child only goes one step, namely to parents. Yet when fetching fetch always go really deep all the way to the parent and persistent store. So I expect things will be the same.
Yet it's not.
I have a managed object context that is parent of all other managed object context.
One child change data and save. The parent is also changed. I do executeFetchRequest on parent and I see that the data change.
However, some child of the parents still use old data. Same object id same data. Somehow the value of the property remain the same.
How to tell the child to reload fresh data from the parent?
To be more exact
Say P is the parent
Say it has C1 C2 C3 as child
Then C1 changes data and commit. The change is propagated to P. However, executing executeFetchRequest at C2 and C3 still shows old data.
What gives?
For example, when I check for the imageBlob property, this is what I get:
Child:
2013-02-05 13:57:42.865 BadgerNew[78801:c07] imageBlob: <UIImage: 0x89c3c50>
2013-02-05 13:57:42.866 BadgerNew[78801:c07] imageBlob: <null>
2013-02-05 13:57:42.866 BadgerNew[78801:c07] imageBlob: <null>
2013-02-05 13:57:42.866 BadgerNew[78801:c07] imageBlob: <null>
Parent:
2013-02-05 13:57:42.868 BadgerNew[78801:c07] imageBlob: <UIImage: 0x114af650>
2013-02-05 13:57:42.868 BadgerNew[78801:c07] imageBlob: <UIImage: 0x8e492e0>
2013-02-05 13:57:42.868 BadgerNew[78801:c07] imageBlob: <UIImage: 0x114c79b0>
2013-02-05 13:57:42.869 BadgerNew[78801:c07] imageBlob: <UIImage: 0xa8c76e0>
Here is a more comprehensive version why I jot down the moc, the parent moc, the blob, the URL and the object ID. Child:
In particular I want the mainqueue managedobject context to be another child of the parent rather than the parent of all other managedObjectContext. On the other hand, I also want the mainQueue Managed object context to have uptodate information. I wonder what the standard solution be.
Upvotes: 17
Views: 4152
Reputation: 21244
There is actually a lot of documentation about how to do this correctly, including WWDC session videos from 2011 and 2012. 2012 session 214 "Core Data Best Practices" would be especially interesting for you.
For example, for your save, it should look like:
[child performBlock:^{
[child save:&error];
[parent performBlock:^{
[parent save:&parentError];
}];
}];
That saves the child, the changes go to the parent and you save on the parent - which would propagate all of those changes correctly to other child contexts. Looking at your question, I think you may run into some other issues with your implementation and Session 214 may be very helpful in resolving them.
As for resetting the context, I would NOT recommend doing that when using parent child contexts. I would also steer away from using refreshObject:mergeChanges:
. Using objectWithID for this purpose may save you a lot of pain as it will make the best use of the managed object context's row cache. It will also only traverse as far as it needs to through the stack of children and parents to satisfy the request.
Upvotes: 0
Reputation: 7381
The child has invalid existing references. If you want the siblings to be in sync after parent save, you must invalidate the children with reset
.
After calling reset
, all the receiver's managed objects are “forgotten.” If you use this method, you should ensure that you also discard references to any managed objects fetched using the receiver, since they will be invalid afterwards.
You can also use refreshObject:mergeChanges:
on the individual objects changed on all the child contexts when saving the parent context if you want finer control on changed objects in the child contexts.
Upvotes: 21