2016-11-29 254 views
0

我正在創建一個iOS應用程序,我希望用戶能夠通過UITableView進行搜索並顯示基於各種不同輸入的結果。我使用的NSPredicate有多個條件用「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!) 

我的參數是名字,姓氏,專業,一年,GPA。當我在搜索欄中輸入除名字以外的任何內容時,不會顯示任何結果。但是輸入名字確實會返回匹配。這是爲什麼發生?我的NSPredicate格式不正確?

回答

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) 

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

我還沒有真正嘗試過這一點,但你可以通過更新每個%@%[email protected]使它更容易些。那麼你只需要一次指定searchController.searchBar.text!

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

NSPredicate不支持位置參數。 –

+0

@MartinR謝謝。我不確定這一點。 – rmaddy

0

沒有測試,但是這應該工作,並可能是對雨燕最簡單的語法,如果你所有的subpredicates是相同的:

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

對於一個簡單的,靜態的,謂語是這樣,我會選擇原生斯威夫特方法:

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:))