NSPredicate用于多字搜索

时间:2011-02-14 15:06:35

标签: nspredicate iphone

在我的iOS应用程序中,我的fetch控制器有一个非常简单的谓词。

NSString *format = [NSString stringWithFormat:@"name like[c] '%@'", nameVar];
NSPredicate *predicate = [NSPredicate predicateWithFormat:format];
[fetchController setPredicate:predicate];

它执行基本的不区分大小写的名称查找。现在我想改变它,以便我可以在搜索框中放置一些单词(nameVar具有搜索框中的值),用空格分隔,并让谓词过滤与所有这些关键字匹配的结果。

所以,如果我有两个名字: “约翰史密斯”和“玛丽史密斯”,我搜索:“史密斯M”我想只有一个结果,但搜索结果如此:“Sm th ith”应该返回两个值。

有谁知道应该如何实施?

1 个答案:

答案 0 :(得分:32)

在常规计算机上

编辑 ...

所以有几点需要注意:

  1. 您不需要在格式字符串中的替换占位符周围添加引号。当该方法正在建设的谓词,它要被创建NSExpressionNSPredicate(具体NSComparisonPredicateNSCompoundPredicate)对象的抽象语法树。您的字符串将被放置在NSExpression类型NSConstantValueExpressionType中,这意味着它的已经将被解释为常规字符串。实际上,将单引号放在格式字符串中会使您的谓词无效。
  2. 您不仅限于谓词中的单个比较。根据它的声音,您希望与搜索字符串中的“单词”进行尽可能多的比较(nameVar)。在这种情况下,我们将nameVar分解为其组成单词,并为每个单词创建一个比较。完成后,我们AND将它们组合在一起创建一个单一的首要谓词。下面的代码就是这样。
  3. 原始回答

    您可以通过构建自己的NSCompoundPredicate

    来实现此目的
    NSString *nameVar = ...; //ex: smith m
    NSArray *names = ...; //ex: John Smith, Mary Smith
    
    NSArray *terms = [nameVar componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    NSMutableArray *subpredicates = [NSMutableArray array];
    
    for(NSString *term in terms) {
      if([term length] == 0) { continue; }
      NSPredicate *p = [NSPredicate predicateWithFormat:@"name contains[cd] %@", term];
      [subpredicates addObject:p];
    }
    
    NSPredicate *filter = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
    [fetchController setPredicate:filter];
    

    警告:在iPhone上的浏览器中输入。