NSPredicate在一对多关系中不区分大小写地匹配

75

我正在实现一个搜索栏,用户可以在其中输入一个字符串来过滤视图中显示的项目。每个被显示的对象都有一个到多个关键词的关系,我希望能够根据它们的关键词来过滤对象。每个关键词对象都有一个名称属性,因此我已经设置了一个NSPredicate来进行过滤,它看起来像这样:

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"keywords.name CONTAINS %@", self.searchString];

这段代码运行良好,但问题是搜索区分大小写,如果关键字有大写字母但用户输入全小写,则找不到匹配项。我尝试了以下修改:

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"keywords.name CONTAINS[c] %@", self.searchString];

但是这并不影响匹配的大小写敏感性。有没有一种方法可以使用普通谓词进行不区分大小写的匹配?或者我需要在关键字类上实现某种自定义访问器,例如编写一个lowercaseName方法并针对搜索字符串的小写版本进行匹配?

补充说明:进一步探索后,添加自定义访问器的解决方法对于手动使用NSPredicate可以正常工作,但在使用Core Data的NSFetchRequest查询属性时根本不起作用,该查询仅适用于在Core Data模型中定义的属性。

5个回答

95

如果我理解正确,您希望在搜索字符串匹配任何关键字名称时,谓词为真。为此,您需要使用ANY关键字进行测试,如下所示:

[NSPredicate predicateWithFormat:@"ANY keywords.name CONTAINS[c] %@", ...];
这将搜索关键词,并在任何一个关键词名称包含您的搜索字符串时返回true。

1
我知道一定有我忽略的方法。非常好用,谢谢! - Brian Webster
还有一个更加优雅的方法是使用[NSPredicate predicatWithFormat:@"%@ IN keywords.name", searchString],但我尝试使用[cd]修饰符时它并不起作用。我还在努力理解其中的原因。 - undefined
@MottiShneor 这并不完全相同。您的谓词要求查询与关键字完全匹配,而CONTAINS将搜索子字符串匹配。 - undefined

56

我相信答案是:

[NSPredicate predicateWithFormat:@"keywords.name CONTAINS[cd] %@", self.searchString];

字符串比较默认是区分大小写和音标的。您可以使用方括号内的关键字符c和d来修改运算符,分别指定不区分大小写和音标敏感性,例如firstName BEGINSWITH[cd] $FIRST_NAME。

谓词格式字符串语法


这基本上与我在原始问题中发布的第二次尝试相同,只是添加变音符标志不同。问题在于当表达式的左侧不是简单字符串时,这种方法无法正常工作。 - Brian Webster
1
对我来说,[d]选项给了我这个错误:Terminating app due to uncaught exception 'Invalid predicate option', reason: 'NSDiacriticInsensitivePredicateOption not supported for string type' - Zeb

13

如果你想捕获仅相等但大小写不敏感的名称,我认为这是最佳解决方案。

[NSPredicate predicateWithFormat:@"ANY keywords.name LIKE[c] %@", ...];

你们帮了我很多。谢谢大家!!!

根据我的情况,我做了:

[NSPredicate predicateWithFormat:@"ANY name LIKE[c] %@", @"teste"];

1
LIKE是匹配通配符(?*)的运算符。只有在您传递给%@的字符串是通配符模式时,它才能正常工作,因为谓词将其解释为一个通配符模式;如果该字符串不是通配符模式,则在期望通配符的位置传递它将会导致问题。如果您想要严格相等,请使用==。 - Peter Hosey
8
哇!这个也管用啊.. == [c]。我还没试过!“glob pattern”是什么?我在谷歌上搜了一下,但是...它是正则表达式吗? - wal
不。Globs是您在shell中使用的一种模式,用于一次匹配多个文件名。 - Peter Hosey
3
小提示:对于正在使用Realm和NSPredicate的人,不支持使用LIKE - Zeb

8

如果您必须匹配关键字,但搜索必须不区分大小写,则应使用 NSPredicate(format: "keywords.name =[c] %@", self.searchString)

LIKE 不适用于字符串常量。


2
如果你想要不区分大小写且带通配符的话,可以使用以下代码:
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"(name like[c] '*%@*')",@"search"]];

1
NSPredicate predicate = [NSPredicate predicateWithFormat:@"(name like[c] '%@*')",@"search"]; 这就足够了。 - Zeb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接