【问题标题】:NSPredicate Formatting IssueNSPredicate 格式问题
【发布时间】:2016-11-29 02:49:29
【问题描述】:

我正在创建一个 iOS 应用程序,我希望用户能够在其中搜索 UITableView 并根据各种不同的输入显示结果。我正在使用具有多个由“OR”分隔的条件的 NSPredicate 来执行此操作,但由于某种原因,它只搜索第一个条件而没有其他条件。

这是我的 NSPredicate 的格式:

let searchPredicate = NSPredicate(format: "(SELF.firstName CONTAINS[c]
%@) OR (SELF.lastName CONTAINS[c] %@) OR (SELF.major CONTAINS[c] %@) OR
(SELF.year CONTAINS[c] %@) OR (SELF.gpa CONTAINS[c] %@)",
searchController.searchBar.text!)

我的参数是 firstName、lastName、major、year 和 gpa。当我在搜索栏中输入除名字之外的任何内容时,没有显示任何结果。但是输入名字确实会返回匹配项。为什么会这样?我的 NSPredicate 格式是否错误?

【问题讨论】:

    标签: ios swift nspredicate


    【解决方案1】:

    您的谓词中有五个%@ 格式说明符实例,因此您需要传递五个值。你只是通过了一个。

    您需要重复searchController.searchBar.text! 五次。顺便说一句 - 将其分配给安全展开的变量并重复该变量五次。打字会更少。

    if let srch = searchController.searchBar.text {
        let searchPredicate = NSPredicate(format: "(SELF.firstName CONTAINS[c] %@) OR
            (SELF.lastName CONTAINS[c] %@) OR
            (SELF.major CONTAINS[c] %@) OR
            (SELF.year CONTAINS[c] %@) OR
            (SELF.gpa CONTAINS[c] %@)", srch, srch, srch, srch, srch)
        ...
    }
    

    【讨论】:

    • NSPredicate 不支持位置参数。
    【解决方案2】:
    if let text = searchController.searchBar.text, text.characters.count > 0{
        var predicates = [NSPredicate]()
        predicates.append(NSPredicate(format: "self.firstName CONTAINS[c]",text))
        predicates.append(NSPredicate(format: "self.lastName CONTAINS[c]",text))
        predicates.append(NSPredicate(format: "self.major CONTAINS[c]",text))
        predicates.append(NSPredicate(format: "self.year CONTAINS[c]",text))
        predicates.append(NSPredicate(format: "self.gpa CONTAINS[c]",text))
    
        let searchPredicate:NSPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicates)
    
        }
    

    【讨论】:

      【解决方案3】:

      未经测试,但如果所有子谓词都相同,这应该可以工作,并且可能是 Swift 最简单的语法:

      if let text = searchController.searchBar.text {
          let myCompondPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: ["firstName", "lastName", "major", "year", "gpa"].map {
              NSPredicate(format: "%K CONTAINS[c] %@", $0, text)
          })
      
          // Do something with myCompondPredicate here..
      }
      

      【讨论】:

        【解决方案4】:

        对于像这样一个简单、静态的谓词,我会选择原生 Swift 方法:

        import Foundation
        
        struct Student {
            let firstName: String
            let lastName: String
            let major: String
            let gpa: Double
        }
        
        extension Student {
            func anyFields(contain searchString: String) -> Bool {
                return firstName.contains(searchString)
                    || lastName.contains(searchString)
                    || major.contains(searchString)
                    || String(gpa).contains(searchString)
            }
        
            // Alternate implementation:
            /* 
            func anyFields(contain searchString: String) -> Bool {
                return [firstName, lastName, major, String(gpa)].contains(where: { field in
                    field.contains(searchString)
                })
            } */
        }
        
        
        let matchingStudents = students.filter(Student.anyFields(contain:))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-10-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多