具有多个条件的 NSPredicate

Posted

技术标签:

【中文标题】具有多个条件的 NSPredicate【英文标题】:NSPredicate with Multiple Conditions 【发布时间】:2014-09-03 03:59:17 【问题描述】:

我正在尝试创建。我找到了几种解决方案,但它们似乎都不适用于我的方法。我找到的最好看的一个如下。

这是我的单一谓词方法,它工作得很好:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name contains[c] %@", 
searchText];
filteredBusinesses = [businesses filteredArrayUsingPredicate:predicate];

这是我的编辑版本,有多个条件。我不确定出了什么问题。有什么想法吗?

NSPredicate *p1 = [NSPredicate predicateWithFormat:@"name contains[c] %@", searchText];
NSPredicate *p2 = [NSPredicate predicateWithFormat:@"businessArea contains[c] %@", 
searchText];

NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[p1, p2]];
filteredBusinesses = [businesses filteredArrayUsingPredicate:predicate];

【问题讨论】:

你期待什么,你得到什么? 我期待能够在我的 searchbardelegage 中输入多种类型的信息。相反,它崩溃了:( 粘贴你的堆栈跟踪 如果你所做的只是过滤一个数组,为什么不使用一个块谓词呢? @matt,我该怎么做? 【参考方案1】:

你可以试试这个

NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[p1, p2]];

【讨论】:

...or 谓词与 and 谓词不同。 OP 想要两个条件来申请要收集的项目。【参考方案2】:

除了@Nikunj 的回答,您还可以像这样使用 NSCompoundPredicate 进行 AND 操作。

Obj-C - 与

NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2]];

斯威夫特 - 与

let predicate1:NSPredicate = NSPredicate(format: "X == 1")
let predicate2:NSPredicate = NSPredicate(format: "Y == 2")
let predicate:NSPredicate  = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1,predicate2] )

Swift 3 - 与

    let predicate1 = NSPredicate(format: "X == 1")
    let predicate2 = NSPredicate(format: "Y == 2")
    let predicateCompound = NSCompoundPredicate.init(type: .and, subpredicates: [predicate1,predicate2])

【讨论】:

【参考方案3】:

您发布的代码中没有任何问题,这意味着错误可能来自您通过过滤数组来评估谓词。

由于第一个谓词有效,问题出在businessArea 键路径上。

在以下情况下过滤数组会引发异常:

    数组中有一个对象没有businessArea 值(例如,它不是具有-businessArea 方法的对象) 该对象确实具有businessArea 值,但该值既不是NSString 也不是nil

【讨论】:

【参考方案4】:

NSCompoundPredicate 进行了改版。以防万一有人在寻找 Swift 5+ 版本:

let predicatesAND = NSCompoundPredicate(andPredicateWithSubpredicates:[pred1,pred2])

let predicatesOR = NSCompoundPredicate(orPredicateWithSubpredicates:[pred1,pred2])

【讨论】:

【参考方案5】:

首先,我怀疑您的两个基本谓词可能存在缺陷。从您的对象名称“企业”来看,它是一个集合,即NSArrayNSSetNSDictionay 项目。在这种情况下,"name contains[c] 'mmm'" 在对整个集合进行评估时没有意义,并且应该崩溃。它缺少集合运算符 (ANY, ALL, SOME) ,例如"ANY name contains[c] 'mmm'".

啊...现在我明白了...您正在使用谓词来过滤 NSArray,这意味着谓词是在每个项目上分别执行的。所以你的谓词没问题。

现在...组合谓词的最简单方法是在格式字符串级别!怎么了

NSPredicate *p1 = [NSPredicate predicateWithFormat:@"name contains[c] %@ AND businessArea contains[c] %@", nameToSearch, areaToSearch]; 

如果你坚持用艰难的方式来做,那么构建你的复合 NSPredicate 也应该奏效 - 只有你对两个条件使用相同的 searchText,这可能会导致谓词永远不匹配。

我的建议是,在评估过滤数组的行上放置一个断点并在过滤之前停止,并在调试器中打印谓词描述,使用调试器命令po p1 你会看到最终形式是什么您的谓词,并且将能够确定您是否正确构建它。

【讨论】:

以上是关于具有多个条件的 NSPredicate的主要内容,如果未能解决你的问题,请参考以下文章

使用具有嵌套或条件的多个 where(或 AND)?

SQL 具有多个条件的多个计数列

XPath 在多个级别具有多个条件?

定义具有多个条件的变量

具有多个条件的组加入,其中一个具有常数

和/或具有满足多个条件的单因素水平的条件过滤