Well, I'm more than happy to file a bug, as it has been tricky to figure out (and I would probably still be at it without your interjection). There are several ways to frame the problem of course: it could be a documentation bug... things aren't as simple as might first appear in the docs/guide, or maybe something can be done to have deleted object behave in a 'friendlier' manner w.r.t. their defunct relationships. I suppose I can just find a general form of words and let you good folks figure out what it really means in practice :-)

I still think I might have something more to figure out here too. At the end of my testing, as an experiment I had a main thread timer fire periodically to perform a save on the main thread's MOC (without performing any changes on the main thread's MOC at all). This induced the same problem, and I'm still curious as to how the main thread's copy of the graph might have the nil in the relationship under these conditions. AFAICS there shouldn't have been any chance for either MOC to be in this condition at any time. I assume the merge operation from the other thread is 'atomic' somehow and activity on another thread (like a save) should not be able to catch that MOC in some kind of in-between state?

Aside from this 'stress' test though, I haven't (yet) got it to fall over - essentially under the conditions where only one thread (albeit one of several threads on any occasion) is making changes and saving at a time.

Cheers

-- Luke


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 (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to