views:

373

answers:

2

With a one-to-many relationship: the generated classes from the xcdatamodel will have:

@interface Department (CoreDataGeneratedAccessors)
- (void)addEmployeeObject:(Employee *)value;
- (void)removeEmployeeObject:(Employee *)value;
- (void)addEmployees:(NSSet *)value;
- (void)remove Employees:(NSSet *)value;
@end

Would 'addEmployees' replace all existing items in the set or will it append to the existing list?

Apple's CoreData Programming Guide notes that you can "manipulate an entire to-many relationship in the same way you do a to-one relationship" and demonstrates it using 'setEmployees' and not the 'addEmployees' that my generated class has.

NSSet *newEmployees = [NSSet setWithObjects:employee1, employee2, nil];
[aDepartment setEmployees:newEmployees];

NSSet *newDirectReports = [NSSet setWithObjects:employee3, employee4, nil];
manager.directReports = newDirectReports;

// for adding single elements
NSMutableSet *employees = [aDepartment mutableSetValueForKey:@"employees"];
[employees addObject:newEmployee];
[employees removeObject:firedEmployee];
// or
[aDepartment addEmployeesObject:newEmployee];
[aDepartment removeEmployeesObject:firedEmployee];
A: 

Would 'addEmployee' replace all existing items in the set or will it append to the existing list?

Because it takes an NSSet*, presumably neither, unless the original set of Department -to- Employee relationships is empty or disjoint to what you're adding, respectively. Think of these Core Data methods as performing set operations, not array manipulations.

As a minor aside, a naming convention is to name to-many relationships with the plural form of the Entity noun (i.e. you might change employee to employees). This will make more sense to anyone else looking at your methods and Core Data model.

Alex Reynolds
Would the set item comparison to determine whether it's a disjoint or not be done based on the value or reference of the specific object in the set?
Alexi Groove
I think the `-isEqual:` method compares the results of the `-hash` method on both managed objects, I believe. See `NSObject` for the definition of `-hash`: http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/hash
Alex Reynolds
What I wrote seems like a non-answer, actually. If the MO have different references in them, they may have a different hash result. It seems easy enough to test this question, though.
Alex Reynolds
A: 

To clarify things: all of the methods in the interface perform set operations because they all refer to a to-many relationship. The difference between addEmployeeObject: and addEmployees: is that the former adds a single object while the latter adds many of them at the same time. The set operation performed is in this case set union, while for removeEmployeeObject: and removeEmployees it is set difference of course.

Why you should not think of this in terms of appending to the previous collection of elements already stored? Because Core Data represents a to-many relationship using a NSSet (a collection of distinct elements), not a NSCountedSet (a set that can contain duplicate elements, also known as a bag). And because a set is an unordered collection therefore "appending" does not make sense (as it does instead for an array or list). Core Data (correctly) does not allow repeated elements stored in the same to-many relationship, therefore the framework uses a NSSet, which enforces distinct elements (while NSCountedSet allows duplicate elements).

Finally, when you use the setEmployees: method, you are releasing the current set of employees stored in the to-many relationships and retaining the set you passed as an argument to the setEmployees: method. Therefore you are changing one-shot the elements stored in the relationship. It is perfectly equivalent to removing first all of the elements stored in the relationship, then adding the new ones (assuming of course they are all distinct).

unforgiven