NSPredicate用于多字搜索

RaY*_*ell 10 iphone nspredicate

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

NSString *format = [NSString stringWithFormat:@"name like[c] '%@'", nameVar];
NSPredicate *predicate = [NSPredicate predicateWithFormat:format];
[fetchController setPredicate:predicate];
Run Code Online (Sandbox Code Playgroud)

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

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

有谁知道如何实施?

Dav*_*ong 32

在常规计算机上编辑 ...

所以有几点需要注意:

  1. 您不需要在格式字符串中的替换占位符周围添加引号.当方法构建谓词时,它将创建一个抽象语法树NSExpressionNSPredicate(特定NSComparisonPredicateNSCompoundPredicate)对象.您的字符串将被置于一个NSExpression类型中NSConstantValueExpressionType,这意味着它已经被解释为常规字符串.实际上,将单引号放在格式字符串中会使您的谓词无法正常工作.
  2. 您不仅限于谓词中的单个比较.从它的声音来看,你希望在搜索字符串(nameVar)中有与"单词"一样多的比较.在这种情况下,我们将分解nameVar为组成单词,并为每个单词创建一个比较.一旦我们完成了这个,我们AND就一起创建一个单一的首要谓词.下面的代码正是如此.

原始答案

您可以通过构建自己的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];
Run Code Online (Sandbox Code Playgroud)

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