How to use core data's add & remove (NSSet) accessor methods?

kangaroo picture kangaroo · Jun 12, 2012 · Viewed 9k times · Source

In this test Core Data project, I have a one to many relationship from "Customer" to "Products" and this relationship is named 'products'. Customer's attribute is 'name' and Product's attribute is 'item'. I've subclassed the entities and Xcode has produced the following for Customer:

@interface Customer : NSManagedObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSSet *products;
@end

@interface Customer (CoreDataGeneratedAccessors)

- (void)addProductsObject:(Products *)value;
- (void)removeProductsObject:(Products *)value;
 - (void)addProducts:(NSSet *)values;
- (void)removeProducts:(NSSet *)values;

@end

To add, let's say, one customer (John Doe) and two items (Widget 1 & Widget 2), I can use the accessor method addProductsObject as follows:

...
// Add (1) customer object
Customer *custObj = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
[custObj setValue:@"John Doe" forKey:@"name"];

// Add (2) products for John Doe
for (int foo=0; foo<2; foo++) {
    self.product = [NSEntityDescription insertNewObjectForEntityForName:@"Products" inManagedObjectContext:context];
    NSString *objString = [NSString stringWithFormat:@"Widget %d", foo];
    self.product.item = objString;
    [custObj addProductsObject:self.product];
}
...

This works fine but, if possible, I'd like to make use of the addProducts accessor.

I'm assuming that the generated accessor method addProducts is there to facilitate the insertion of a 'set' of objects with something like:

...
NSSet *itemSet = [[NSSet alloc] initWithObjects:@"Widget 1", @"Widget 2", nil];
[custObj addProducts:itemSet];
...

but this fails. In this try, I understand a product object hasn't been explicitly created and, as such, an explicit product assignment hasn't taken place but I thought, perhaps, the accessor would take care of that.

What, therefore, is the correct usage of addProducts, and for that matter, removeProducts?

Thanks.

Answer

The set you are passing to addProducts contains NSString, not Products.

NSMutableSet* products = [NSMutableSet set];

Products* product = [NSEntityDescription insertNewObjectForEntityForName: @"Products" inManagedObjectContext: context];
product.item = @"Widget 1";
[products addObject: product];

product = [NSEntityDescription insertNewObjectForEntityForName: @"Products" inManagedObjectContext: context];
product.item = @"Widget 2";
[products addObject: product];

[customer addProducts: products];

Per se, the accessor have no way to know what the strings you gave it in first place were for. You have to provide a set containing the right kind of entities.

That said, you can define your own accessor, taking a set of strings and inserting properly initialized Products in your relationship : addProductsWithStrings: per example.