What is the best way to build a complex NSCompoundPredicate?
What you need to do is to create a Predicate for each one of your clauses. For example let's break down your query:
- SELECT * FROM TRANSACTIONS
- WHERE CATEGORY IN (categoryList)
- AND LOCATION IN (locationList)
- AND TYPE IN (typeList)
- AND NOTE contains[cd] "some text"
- AND DATE >= fromDate AND DATE <+ toDate
Based on this, you have 5 predicates (2-6). So let's work on them one by one.
NSPredicate *inCategoryPredicate = [NSPredicate predicateWithFormat:@"Category IN %@", categoryList]; NSPredicate *locationPredicate = [NSPredicate predicateWithFormat:@"Location IN %@", locationList]; NSPredicate *typePredicate = [NSPredicate predicateWithFormat:@"Type IN %@", typeList]; NSPredicate *notePredicate = [NSPredicate predicateWithFormat:@"Note contains[c] %@", @"Some Text"]; NSPredicate *startDatePredicate = [NSPredicate predicateWithFormat:@"Date => @", fromDate]; NSPredicate *endDatePredicate = [NSPredicate predicateWithFormat:@"Date <= @", toDate];
Now you just need to join them into just one predicate: Apple's documentation states:
You should structure compound predicates to minimize the amount of work done. Regular expression matching in particular is an expensive operation. In a compound predicate, you should therefore perform simple tests before a regular expression;
This being said then you should start with the "easy" predicates first. So:
NSCompoundPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects: startDatePredicate, endDatePredicate, inCategoryPredicate, locationPredicate, typePredicate, notePredicate];
You can always get an idea of what the predicate (sql where) looks like if you NSLog it.