Re: Strange Core Data save behaviour ("required relationship nil"... when it is set the line before saving)
Re: Strange Core Data save behaviour ("required relationship nil"... when it is set the line before saving)
- Subject: Re: Strange Core Data save behaviour ("required relationship nil"... when it is set the line before saving)
- From: Luke Evans <email@hidden>
- Date: Fri, 16 Oct 2009 16:29:07 -0700
Darn, I thought his problem had gone away, but I still get the failure
to save from time to time (the probability of occurrence is pretty low
though).
I'm even setting the problematic relationship to nil before deleting
the object, then calling "-processPendingChanges", then saving the
object (which will then cause other thread's MOCs to be updated via -
mergeChangesFromContextDidSaveNotification.
I currently don't understand the difference between the many cases
that seem to work, and the case that then suddenly doesn't. Again,
while the change can be introduced by a number of threads, only one
MOC is changed (and saved) at a time, and this MOC is strictly
associated with the thread.
I need to spend more time researching this problem, but the issue
seems to raise its head when I'm testing some 'quick fire' changes
between types of my object B (where old B gets deleted, new B created
and linked into the owning object A).
I'm wondering if it's possible to have a change come in on the second
thread, just as the change before it is being processed from the other
thread, somehow leaving the second thread's MOC in an odd state, and
unable to save. I'm pretty sure the Context Did Save Notifications
and behaviour of -mergeChagnesFromContextDidSaveNotification are
synchronous though, so should offer no opportunity for interleaving in
my current test regime. In any case, there's certainly no locking on
my part, and I've been assuming that changes propagating from an
earlier change in another MOC (via -
mergeChangesFromContextDidSaveNotification) would be atomic, or
otherwise would automatically act correctly when a changed is
attempted on an object that has been changed in another MOC.
Should I be calling -[NSManagedObjectContext
refreshObject:mergeChanges:] on any object in any MOC before I attempt
to make any changes to it? I don't read anything suggesting this is
necessary, though maybe it is safer if it gives the object a change to
be fully updated from other MOCS (??).
I'm clutching at straws a little here, I realise... no substitute for
actually trying to grok the dynamics, but there's a lot about what
actually happens when you do a -
mergeChangesFromContextDidSaveNotification that remains opaque (to me).
-- lwe
On 2009-09-29, at 8:16 PM, Ben Trumbull wrote:
On Sep 29, 2009, at 8:22 PM, Luke Evans wrote:
Hello Ben.
What happens if you add a call to -processPendingChanges in
between #2 and #3 ?
... well then everything works wonderfully (oh joy!!) :-)
OK. I need to get a proper mental picture of why this is needed in
this case.
I guess I was vaguely aware of this method from previous passes
though the Core Data docs, but...
- The method documentation itself doesn't _really_ suggest it may
be essential in some cases. Rather, the talk is about getting the
undo manager into step, and even then the statement is made that
this is done by default at the end of the run loop.
- deleteObject docs, or indeed the guide section on deleting
(Creating and Deleting Managed Objects) makes no mention of a need
to call this method
- I had tried manually setting the old deleted objects 'back
relationship' to nil, before deleting it, and before setting A's
relationship to the new B. This hadn't worked, but was my attempt
to keep the relationships consistent - at least in in the MOC that
induced the change.
It's tempting to just think that you should _always_ do a -
processPendingChanges before a -save:, but I'd prefer to understand
what's really happening here.
It's not before the save. It's in between the deletion and the re-
assignment of the relationship of the surviving object to a new
object. The problem is reassigning the relationship before delete
propagation runs. Delete propagation, as well as the change
notifications and several other aspects of object graph change
tracking are coalesced and run later. Calling
processPendingChanges is one of those later times. The application
event loop also calls it, which is the default timing. Executing a
fetch, or a save will also call it.
Manually setting the deleted object's relationship instead of
calling processPendingChanges between steps #2 & #3 should also work.
I don't think anyone has cared enough to file a bug on this.
- Ben
If you have insights on the above, then that would be great.
Regardless, you've just improved my humour by several degrees ;-)
-- Luke
On 2009-09-29, at 3:59 PM, Ben Trumbull wrote:
Now, I have some code that changes the value of the 'B enumeration
value' that A is using. This does the following:
1. Create a new instance of the B subentity that represents the
value
we want (in the same MOC as A)
2. Delete the old B object that A was pointing to, i.e. [moc
deleteObject:B];
3. Set A's to-one relationship to point to the new B object (and
for
good measure, set B's inverse relationship - though this should be
done automagically).
4. Save the moc
4. is where badness happens (failed to save). The error tells me
that
A's relationship property to B is nil... but just before I do the
save
I log the value of the object referenced by this relationship and
it's
the new 'B' object!
I have no idea what I've done to upset Core Data such that it
claims a
relationship is nil when I save, but the line before the [moc
save:&err], the relationship shows as referencing a perfectly good
object.
So you delete B, which has an inverse relationship to A. Then you
set a new B on A. Then you save, and delete propagation cleans up
the graph, nullifying the old B's inverse relationship ?
What happens if you add a call to -processPendingChanges in
between #2 and #3 ?
- Ben
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden