具有多个条件的 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】:首先,我怀疑您的两个基本谓词可能存在缺陷。从您的对象名称“企业”来看,它是一个集合,即NSArray
、NSSet
或NSDictionay
项目。在这种情况下,"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的主要内容,如果未能解决你的问题,请参考以下文章