NSPredicate格式问题

时间:2016-11-29 02:49:30

标签: ios swift nspredicate

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

以下是我的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格式不正确吗?

4 个答案:

答案 0 :(得分:2)

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

您需要重复searchController.searchBar.text!五次。 BTW - 将其分配给安全解包的变量并重复该变量五次。输入的次数会减少。

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)
    ...
}

答案 1 :(得分:1)

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)

    }

答案 2 :(得分:0)

未经测试但这应该有效,如果所有的子预测都相同,则可能是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..
}

答案 3 :(得分:0)

对于像这样的简单静态谓词,我会选择原生的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:))