views:

376

answers:

2

Hi,

Just wondering what the best way to build a NSPredicate is if some filters are optional?

This is basically for a filter, so if some options aren't selected I don't to filter by them

eg. If I have option1 and option2 set for the filter.

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"option1 = %@ AND option2 = %@] ....

otherwise if just option1 NSPredicate* predicate = [NSPredicate predicateWithFormat:@"option1 = %@] ....

The key being there are 10 different options to filter, so I don't want to have to code for the 10x10 possible combinations.

Thanks

+1  A: 

predicateWithFormat: takes an NSString. So all you have to do is build the string based on the options selected (using a for-loop to append to an NSMutableString, etc.) and pass it to predicateWithFormat:

Diederik Hoogenboom
Not sure thats totally trueThis works:[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"startTime >= %@", from]];This crashes:[fetchRequest setPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"startTime >= %@", from]]];
John
John: That's because you added `stringWithFormat:`. Don't do that. Do what Diederik suggested instead (or use `componentsJoinedByString:`, which does the loop for you).
Peter Hosey
+2  A: 

John, have a look at building and retaining the "sub-predicates" as templates and then use your logic branches to build a compound predicate to perform the filtering

/* Retain these predicate templates as properties or static variables */
NSPredicate *optionOneTemplate = [NSPredicate predicateWithFormat:@"option1 = $OPTVALUE"];
// .. and so on for other options

NSMutableArray *subPredicates = [NSMutableArray arrayWithCapacity:10];

/* add to subPredicates by substituting the current filter value in for the placeholder */
if (!!optionOneValue) {
  [subPredicates addObject:[optionOneTemplate predicateWithSubstitutionVariables:[NSDictionary dictionaryWithObject:optionOneValue forKey:@"OPTVALUE"]]];
}
// .. and so on for other option values

/* use the compound predicate to combine them */
NSPredicate *filterPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];

// Now use your filterPredicate

You might want to use a dictionary to keep the set of predicate templates nice and organised, but the example above shows the basic steps.

Rob.

ohhorob