Reputation: 197
First off: sorry if the title isn't very clear, I couldn't quite put my question into short words!
Please consider the following scenario:
- You are using Core Data for storing objects
- You want to fetch objects from your context
- You want to include a predicate to only fetch objects with certain properties
- You have an NSDictionary containing key-value pairs where the key represents the property name and the value represents the desired value to match against
How is best to achieve this?
I currently have the following, which is a quick and probably inefficient way of achieving this:
NSDictionary *attributes = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects:@"value1", @"value2", nil] forKeys: [NSArray arrayWithObjects:@"attr1", @"attr2", nil] ];
// Build predicate format
NSString *predicate = @"";
NSMutableArray *predicateArguments = [[NSMutableArray alloc] init];
int index = 0;
for (NSString *key in attributes) {
NSString *value = [attributes objectForKey: key];
predicate = [predicate stringByAppendingFormat: @"(%@ = %@) %@", key, @"%@", index == [attributes count]-1 ? @"" : @"AND "];
[predicateArguments addObject: value];
index++;
}
NSPredicate *matchAttributes = [NSPredicate predicateWithFormat:predicate argumentArray:predicateArguments];
--
Is there a shorter or more efficient way of achieving this predicate?
Please be aware that block predicates are not an option due to not being supported with NSFetchRequest (Core Data)
Upvotes: 2
Views: 1273
Reputation: 539955
A slightly shorter and perhaps more elegant way is to use a NSCompoundPredicate
:
NSDictionary *attributes = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects:@"value1", @"value2", nil] forKeys: [NSArray arrayWithObjects:@"attr1", @"attr2", nil] ];
// Build array of sub-predicates:
NSMutableArray *subPredicates = [[NSMutableArray alloc] init];
for (NSString *key in attributes) {
NSString *value = [attributes objectForKey: key];
[subPredicates addObject:[NSPredicate predicateWithFormat:@"%K = %@", key, value]];
}
// Combine all sub-predicates with AND:
NSPredicate *matchAttributes = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
ADDED: Even better (thanks to Paul.s):
NSMutableArray *subPredicates = [[NSMutableArray alloc] init];
[attributes enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
[subPredicates addObject:[NSPredicate predicateWithFormat:@"%K = %@", key, value]];
}];
NSPredicate *matchAttributes = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
Upvotes: 4