开发者

Is there a more efficient alternative to find an object with a to-one relationship to two objects I have?

开发者 https://www.devze.com 2023-02-17 00:50 出处:网络
I have the following Core Data setup: Project has-many Answer Field has-many Answer Answer has-one Field

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];
}
0

精彩评论

暂无评论...
验证码 换一张
取 消