在NSPredicate模板中替换字段名称

时间:2012-01-03 09:38:33

标签: objective-c core-data nspredicate

我需要建立一个动态的NSPredicates。我发现使用字符串文件非常方便,我可以应用替换变量。这就是我在文件中所做的。

start<=$START AND end>=$END

这是驻留在实用程序方法中的代码片段:

-(NSPredicate*)predicateWithName:(NSString*)name andVariables:(NSDictionary*)dict { 
    NSURL *queryFile = [[NSBundle mainBundle] URLForResource:name withExtension:@"query"];
    //... 
    NSString *query = [NSString stringWithContentsOfURL:queryFile encoding:NSStringEncodingConversionAllowLossy error:&err];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:query];
    return [predicate predicateWithSubstitutionVariables:dict];
}

一切都运行得很好,但是现在我需要添加动态字段,基于某些条件我想查询特定字段,但我找不到实现此目的的方法。查询文件可能变为:

start<=$START AND end>=$END AND $FIELD_NAME==1

$ FIELD_NAME名称将替换为引号,但查询无效。我知道我可以使用%K作为密钥,但似乎没有办法用字典做这个。

感谢

1 个答案:

答案 0 :(得分:2)

所以,我知道没有内置的方法可以做到这一点。但是,写自己很简单。您可以轻松编写一个NSPredicate类别方法,用一个关键路径表达式替换以KEY_开头的变量,如下所示:

- (NSPredicate *)predicateWithEnhancedSubstitutionVariables:(NSDictionary *)vars {
  if ([self isKindOfClass:[NSCompoundPredicate class]]) {
    // recurse for compound predicates
    NSCompoundPredicate *compound = (NSCompoundPredicate *)self;
    NSMutableArray *subpredicates = [NSMutableArray array];
    for (NSPredicate *subpredicate in [compound subpredicates]) {
      NSPredicate *new = [subpredicate predicateWithEnhancedSubstitutionVariables:vars];
      [subpredicates addObject:new];
    }
    return [[[NSCompoundPredicate alloc] initWithType:[compound compoundPredicateType] 
                                        subpredicates:subpredicates] autorelease];
  } else {
    NSPredicate *final = self;
    // on comparison predicates, pull out the left and right expressions
    NSComparisonPredicate *comparison = (NSComparisonPredicate *)self;
    NSExpression *left = [comparison leftExpression];

    // substitute, if appropriate
    if ([left expressionType] == NSVariableExpressionType) {
      NSString *variable = [left variable];
      if ([variable hasPrefix:@"KEY_"]) {
        NSString *replacement = [vars objectForKey:variable];
        if (replacement) {
          left = [NSExpression expressionForKeyPath:replacement];
        }
      }
    }

    // substitute, if appropriate
    NSExpression *right = [comparison rightExpression];
    if ([right expressionType] == NSVariableExpressionType) {
      NSString *variable = [right variable];
      if ([variable hasPrefix:@"KEY_"]) {
        NSString *replacement = [vars objectForKey:variable];
        if (replacement) {
          right = [NSExpression expressionForKeyPath:replacement];
        }
      }
    }

    // build and return the appropriate comparison predicate
    if (left != [comparison leftExpression] || right != [comparison rightExpression]) {
      if ([comparison customSelector] != NULL) {
        final = [NSComparisonPredicate predicateWithLeftExpression:left 
                                                   rightExpression:right 
                                                    customSelector:[comparison customSelector]];
      } else {
        final = [NSComparisonPredicate predicateWithLeftExpression:left 
                                                   rightExpression:right 
                                                          modifier:[comparison comparisonPredicateModifier] 
                                                              type:[comparison predicateOperatorType] 
                                                           options:[comparison options]];
      }
    }
    return [final predicateWithSubstitutionVariables:vars];
  }
}

有了这个,你应该能够做到:

NSPredicate *p = [NSPredicate predicateWithFormat:@"$KEY_DATE = $DATE"];
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:@"myDateProperty", @"KEY_DATE", aDate, @"date", nil];

p = [p predicateWithEnhancedSubstitutionVariables:d];

然后回复一个谓词,好像你已经完成了:

NSPredicate *p = [NSPredicate predicateWithFormat:@"myDateProperty = %@", aDate];

警告:在浏览器中键入,未编译,yadda yadda