您需要创建一个复合谓词,其最终形式取决于用户搜索的属性。
最简洁的解决方案是使用NSExpression、NSComparisonPredicate 和NSCompoundPredicate 在代码中构建谓词。这将允许您为每个搜索自定义谓词。
类似这样的:
-(NSPredicate *) predicateWithStudyID:(NSString *) aStudyID studyName:(NSString *) aStudyName date:(NSDate *) aDate{
NSPredicate *p;
NSMutableArray *preds=[[NSMutableArray alloc] initWithCapacity:1];
if (aDate != nil) {
NSExpression *dateKeyEx=[NSExpression expressionForKeyPath:@"studyDate"];
NSExpression *aDateEx=[NSExpression expressionForConstantValue:aDate];
NSPredicate *datePred=[NSComparisonPredicate predicateWithLeftExpression:dateKeyEx
rightExpression:aDateEx
modifier:NSDirectPredicateModifier
type:NSEqualToPredicateOperatorType
options:0];
[preds addObject:datePred];
}
if (![aStudyID isEqualToString:@""]) {
NSExpression *studyIDKeyEx=[NSExpression expressionForKeyPath:@"studyID"];
NSExpression *aStudyIDEx=[NSExpression expressionForConstantValue:aStudyID];
NSPredicate *studyIDPred=[NSComparisonPredicate predicateWithLeftExpression:studyIDKeyEx
rightExpression:aStudyIDEx
modifier:NSDirectPredicateModifier
type:NSLikePredicateOperatorType
options:NSCaseInsensitivePredicateOption];
[preds addObject:studyIDPred];
}
if (![aStudyName isEqualToString:@""]) {
NSExpression *studyNameKeyEx=[NSExpression expressionForKeyPath:@"studyName"];
NSExpression *aStudyNameEx=[NSExpression expressionForConstantValue:aStudyName];
NSPredicate *studyNamePred=[NSComparisonPredicate predicateWithLeftExpression:studyNameKeyEx
rightExpression:aStudyNameEx
modifier:NSDirectPredicateModifier
type:NSLikePredicateOperatorType
options:NSCaseInsensitivePredicateOption];
[preds addObject:studyNamePred];
}
p=[NSCompoundPredicate andPredicateWithSubpredicates:preds];
[preds release];
return p;
}
那么你会像这样使用它:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSDate *firstDate=[NSDate date];
NSDate *secondDate=[firstDate dateByAddingTimeInterval:60*60*24];
NSDate *thirdDate=[secondDate dateByAddingTimeInterval:60*60*24];
// I use an array of dictionaries for convenience but it works
// for managed objects just as well.
NSDictionary *d1=[NSDictionary dictionaryWithObjectsAndKeys:
@"abc123", @"studyID",
@"firstStudy", @"studyName",
firstDate, @"studyDate",
nil];
NSDictionary *d2=[NSDictionary dictionaryWithObjectsAndKeys:
@"abc456", @"studyID",
@"secondStudy", @"studyName",
secondDate, @"studyDate",
nil];
NSDictionary *d3=[NSDictionary dictionaryWithObjectsAndKeys:
@"abc789", @"studyID",
@"thirdStudy", @"studyName",
thirdDate, @"studyDate",
nil];
NSArray *a=[NSArray arrayWithObjects:d1,d2,d3, nil];
NSPredicate *p=[self predicateWithStudyID:@"" studyName:@"thirdStudy" date:thirdDate];
NSLog(@"p = %@",p);
NSArray *filtered=[a filteredArrayUsingPredicate:p];
NSLog(@"%@",filtered);
return YES;
}
见Predicate Programming Guide: Creating Predicate Directly in Code
更新:
@DaveDelong 下面指出,在上面的第一段代码中,我创建的子谓词过于复杂。在这种情况下(除了执行速度)不需要从表达式生成子谓词。而是像平常一样构建子谓词,然后像这样复合它们:
-(NSPredicate *) predicateWithStudyID:(NSString *) aStudyID studyName:(NSString *) aStudyName date:(NSDate *) aDate{
NSPredicate *p;
NSMutableArray *preds=[[NSMutableArray alloc] initWithCapacity:1];
if (aDate != nil) {
NSPredicate *datePred=[NSPredicate predicateWithFormat:@"studyDate==%@",aDate];
[preds addObject:datePred];
}
if (![aStudyID isEqualToString:@""]) {
NSPredicate *studyIDPred=[NSPredicate predicateWithFormat:@"studyID Like %@",aStudyID];
[preds addObject:studyIDPred];
}
if (![aStudyName isEqualToString:@""]) {
NSPredicate *studyNamePred=[NSPredicate predicateWithFormat:@"studyName Like %@",aStudyName];
[preds addObject:studyNamePred];
}
p=[NSCompoundPredicate andPredicateWithSubpredicates:preds];
[preds release];
return p;
}