How to store a NSSet (one-to-many) using Core Data?
I am wondering how I can programmatically update a Core Data object. The object is a NSSet though. So I can summarize this with the scheme below:
Property
---------
name
price
typology
Property_has_typology
---------------------
typology_id
property
There is a one-to-many relationship between the Property and Property_has_typology. As one property might have several typologies (aka categories) such as Bed & Breakfast, Villa, Hotel, Mansion, Country House.
So I let the user select multiple rows in my TableView and when he clicks save I want to store these changes. So I do:
NSMutableArray *storeItems = [[NSMutableArray alloc] init];
//Get selected items
for (int i = 0; i < [items count]; i++) {
Properties_has_typology *typo = [NSEntityDescription insertNewObjectForEntityForName:@"Properties_has_typology"
inManagedObjectContext: [PropertyProvider sharedPropertyProvider].context];
typo.typology_id = [NSNumber numberWithInt: (int)[items objectAtIndex:i]];
typo.property = property;
[storeItems addObject: typo];
}
//Store the items for the Property and save it
if ([storeItems count] > 0) {
NSLog(@"Going to save...");
NSSet *storeSet = [[NSSet alloc] initWithArray:storeItems];
property.typology = storeSet;
[property save];
[storeSet release];
}
This kinda works, the issue though is that it doesn't really update the existing values. It just overrides it. So if I save the same two items twice (just as an example) I'd get the开发者_运维技巧 following in my database:
PK TYPOLOGY
------------
1 |
2 |
3 | 4
4 | 6
So yes they are being stored, but it also creates empty rows (clears them instead of deleting/updating them).
Any help would be appreciated. Thanks!
//call
NSArray* oldTypos = [property.typology allObjects];
[[property removeTypology:[PropertyProvider sharedPropertyProvider].context];
[[property addTypology:storeSet];
for(int i = 0; i < [oldTypos count]; i++){
[[PropertyProvider sharedPropertyProvider].context deleteObject:[oldTypos:objectAtIndex:i]];
}
Error* error = nil;
if(![[PropertyProvider sharedPropertyProvider].context save:&error]){
abort();
}
//Also, rename the to-many relationship to plural.
Apologies of there are any typos. I am on my windows machine at the moment so I cannot check it.
TechZen says: I just noticed after the fact that I reversed the to-many relationship that the parent described. However, everything works the same way. I'll edit when I find time.
You are working to hard by doing things manually that Core Data does automatically. To set a relationship you just set one side of it and the managed object context sets the other automatically.
So, if you have a data model like this:
Property{
typology<<-->Property_has_typology.properties
}
Property_has_typology{
properties<-->>Property.typology
}
Then to set the the relationship from the Property
object side you just use:
aPropertyObject.typology=aProperty_has_typologyObject;
To set if from the Property_has_typology
object side you use the relationship accessor methods in the implementation (.m) that Core Data generated for you:
[aProperty_has_typologyObject addPropertiesObject:aPropertyObject];
or
[aProperty_has_typologyObject addPropertiesObjects:aSetOfPropertyObjects];
... and you are done.
Core Data wouldn't provide much utility if you had to manage all the object relationships by hand.
精彩评论