Is there a more efficient alternative to find an object with a to-one relationship to two objects I have?
I have the following Core Data setup:
Project has-many Answer
Field has-many Answer
Answer has-one Field
Answer has-one Project
I need to find the Answer for each Field that is also owned by Project. I'm currently using a predicate for this and executing a fetch request:
NSEntityDescription *answerEntity = [NSEntityDescription entityForName开发者_StackOverflow社区:@"Answer" inManagedObjectContext:self.managedObjectContext];
NSPredicate *answerPredicate = [NSPredicate predicateWithFormat:@"ANY project == %@ && field == %@", self.project, self.field];
NSFetchRequest *answerRequest = [[NSFetchRequest alloc] init];
[answerRequest setEntity:answerEntity];
[answerRequest setPredicate:answerPredicate];
NSError *error = nil;
NSArray *predicates = [self.managedObjectContext executeFetchRequest:answerRequest error:&error];
I'm still new to Core Data but I believe the fetchRequest is querying the database each time I call it, is there a more efficient way of finding these Answer objects?
If I understand correctly, you already have a Field object and an Project object and you want to find the Answer objects they have in common.
If so, the solution is a simple intersect set operation:
NSSet *answersInCommon=[[aFieldObj mutableSetValueForKey:@"answers"] intersectSet:[aProjectObj mutableSetValueForKey:@"answers"]];
... which will return only those Answer objects that appear in both relationships.
Update:
@pdenya in comment provides an enhancement :
Just want to clarify a minor error and a small point that makes this less than ideal. intersectSet returns (void) so the syntax for this would be:
NSMutableSet *answers=[field mutableSetValueForKey:@"answers"];
[answers intersectSet:[project mutableSetValueForKey:@"answers"]];
This solution also modifies the aFieldObj.answers array meaning you can't use this while iterating. setWithSet clears this right up. Example:
NSMutableSet *answers = [NSMutableSet setWithSet:[project mutableSetValueForKey:@"answers"]];
[answers intersectSet:[field mutableSetValueForKey:@"answers"]];
@pdenya's is the correct form.
Best alternate method I've found so far:
NSMutableSet *answers = [self.project mutableSetValueForKey:@"answers"];
NSPredicate *answerPredicate = [NSPredicate predicateWithFormat:@"field == %@", field];
[answers filterUsingPredicate:answerPredicate];
NSManagedObject *answer = nil;
if([answers count] > 0) {
answer = [[answers allObjects] objectAtIndex:0];
}
精彩评论