Mailing Lists: Apple Mailing Lists
Image of Mac OS face in stamp
re: setPrimitiveValue:forKey: and to-many relationships
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

re: setPrimitiveValue:forKey: and to-many relationships



Sean, Jon,

The documentation is correct for 10.4. On 10.5, things are more forgiving, and you can call -setPrimitiveValue:forKey: with a public set. We won't use that object, but we will use its contents. It does no inverse maintenance, so unless it's part of the public setter for the relationship, it's a pretty awful idea.

"If you try to set a to-many relationship to a new NSMutableSet object,
it will (eventually) fail."


Eventually?! What does that even mean? Will it fail later during -
[NSManagedObjectContext save:]? When an managed object is turned into a
fault and then paged back in? When? Can I write a test case to
consistently recreate the failure on-demand?


The to-many relationship object is itself a private subclass of NSSet, so eventually will occur when someone gets back the improperly assigned set, and tries to use it. With -mutableSetValueForKey: or any number of other operations. "eventually == implementation dependent behavior == answer is still no" I suppose you could write a test case on Tiger that failed on-demand.

On Leopard, it's important to realize that you won't get back the object you assigned if you try to do this. In general, the Xcode template generation in the Design menu is the recommended form.

Second, providing sample code to correctly handle this case, they write:

"first get the existing set using primitiveValueForKey: (ensure the
method does not return nil)..."

What should I do if/when the method does return nil? assert() it and
fail immediately because that means the entire object graph is corrupted
and saving will lead to data loss? NSAssert() on it as a warning to the
caller but press on (silently doing nothing)?


It should never return nil, unless you do something very wrong, like try to set values in the faulting callbacks (will or didTurnIntoFault). Within the scope of turning the object into a fault, you should send such messages to nil (e.g. /dev/null )

Right now I'm simply directly assigning my desired NS[Mutable]Set in
that case, like so:

- (void)setChildren:(NSSet*)value_
{
[self willChangeValueForKey:@"children"];
NSMutableSet *mutableRelationshipSet = [[[self
primitiveValueForKey:@"children"] mutableCopy] autorelease];
if (mutableRelationshipSet) {
[mutableRelationshipSet setSet:value_];
[self setPrimitiveValue:mutableRelationshipSet forKey:@"children"];
} else {
[self setPrimitiveValue:value_ forKey:@"children"];
}
[self didChangeValueForKey:@"children"];
}


Is that wrong?

The recommended form of implementing a custom accessor with a Core Data property can be created in Xcode using the Design menu -> Data Model -> Copy ObjC 2.0 Method Implementation when you have that property(ies) selected in the model view.


You are strongly encouraged to use the built in accessor methods, and the templates provided as much as possible. For example, this setter will cause a lot of KVO notifications to get generated. It is very inefficient compared to -addChildren, -removeChildren, and - addChildrenObject, and -removeChildrenObject. Examining the template generation for those methods should give you an idea why.

In this case, you're not doing anything custom at all, and should just use Core Data's default -setChildren method, which you will get with a dynamic property declaration. Actually, you get it anyway, the property declaration just tells the compiler not to warn.

Quincey's suggestions are apt.

As repeated in the Core Data documentation, the primitive accessor methods are intended exclusively as building blocks for the creation of custom public accessors, and should not be used for other purposes. The relationship maintenance (inverses) may be maintained via KVO, so directly using the primitive setter on a relationship without issuing the correct KVO notifications is dangerous and wrong.

- 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




Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2011 Apple Inc. All rights reserved.