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

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

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

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,我该怎么做?

标签: ios objective-c nspredicate


【解决方案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 键路径上。

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

    1. 数组中有一个对象没有businessArea 值(例如,它不是具有-businessArea 方法的对象)
    2. 该对象确实具有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 你会看到最终形式是什么您的谓词,并且将能够确定您是否正确构建它。

        【讨论】:

          猜你喜欢
          • 2011-08-25
          • 2012-04-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多