Re: Core Data compound keys
Re: Core Data compound keys
- Subject: Re: Core Data compound keys
- From: Conor <email@hidden>
- Date: Thu, 02 Aug 2007 01:26:40 +0200
Since nobody more experienced has responded to your mailing I would suggest
that you build the tag checking into a subclass of NSManagedObject. You set
the Core Data object articles to the subclass and then implement a set and
get tags method that stores the tags in a many to many relationship, while
checking that they only link once. It would go something like this:
- (NSString *)tags {
NSSet *tagsSet = [self valueForKey:@"tagsSet"];
if ([tagsSet count] != 0) {
NSMutableString *tagsString = [NSMutableString string];
NSArray *tagsArray = [tagsSet allObjects];
tagsArray = [tagsArray sortedArrayUsingDescriptors:[NSArray
arrayWithObject:[[[NSSortDescriptor alloc] initWithKey:@"name"
ascending:YES] autorelease]]];
NSEnumerator *tagsEnum = [tagsArray objectEnumerator];
NSString *nextTagName;
while (nextTagName = [[tagsEnum nextObject] valueForKey:@"name"]) {
if ([tagsString length])
[tagsString appendString:@", "];
[tagsString appendString:nextTagName];
}
return tagsString;
}
return nil;
}
- (void)setTags:(NSString *)aString {
if ((aString == nil && [[self primitiveValueForKey:@"tagsSet"] count] ==
0) || [aString isEqualToString:[self tags]])
return;
NSMutableSet *tagsSet = [self mutableSetValueForKey:@"tagsSet"];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Tag"
inManagedObjectContext: managedObjectContext];
NSArray *tags = [aString componentsSeparatedByString:@", "];
NSMutableSet *tagsAdded = [NSMutableSet set];
NSError *fetchError;
NSFetchRequest * fetch = [[NSFetchRequest alloc] init];
[fetch setEntity: entity];
NSEnumerator *tagsEnum = [tags objectEnumerator];
NSString *nextTagName;
while (nextTagName = [tagsEnum nextObject]) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name
like[c] %@", nextTagName];
[fetch setPredicate: predicate];
NSArray * results = [managedObjectContext executeFetchRequest:fetch
error:&fetchError];
//Fetch succesfull
if ([results count]) {
if (![tagsSet containsObject:[results objectAtIndex:0]]) {
[tagsSet addObject:[results objectAtIndex:0]];
}
[tagsAdded addObject:[results objectAtIndex:0]];
}
else if ([results count] == 0) {
//Create new Tag
NSManagedObject* aTag = [NSEntityDescription
insertNewObjectForEntityForName:@"Tag" inManagedObjectContext:
managedObjectContext];
[aTag setValue:nextTagName forKey:@"name"];
[tagsSet addObject: aTag];
[tagsAdded addObject: aTag];
}
else if (results == nil) {
NSLog(@"Fetch Error setTagsString: %@ reason: %@ with: %@",
[fetchError localizedDescription], [fetchError localizedFailureReason],
fetch);
}
}
[fetch release];
//remove any tags that were deleted and are not present in the Set of
tagsAdded we just created
NSEnumerator *tagsObjectsEnum = [tagsSet objectEnumerator];
NSManagedObject *nextTag;
while (nextTag = [tagsObjectsEnum nextObject]) {
if (![tagsAdded containsObject:nextTag]) {
[tagsSet removeObject: nextTag];
if ([[nextTag primitiveValueForKey:@"entries"] count] == 0)
[managedObjectContext deleteObject:nextTag];
}
}
}
Type in mail, so check for typos and the such. But this would be the general
idea. The many to many relationship is to a key tagsSet that is an object
that has an attribute with key name. In this case I am turning the tags into
a coma separated string to present to the user; so I would also go further
and save the results as a transient attribute for caching. I also just
started with Core Data so I am not talking from experience.
Regards,
Conor
http://www.bruji.com/
_______________________________________________
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