'Can't use in/contains operator with collection'

匿名 (未验证) 提交于 2019-12-03 01:36:02

问题:

I'm getting this error when clicking on the search bar:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Can't use in/contains operator with collection Assignment_4.SearchResult(studentID: "1060", lastName: "Squarepants", firstName: "Spongebob", major: "Krusty Krab Chef", year: "Junior", gpa: "4.0") (not a collection)'

Getting the error on this line.

let array = (results as NSArray).filtered(using: searchPredicate) 

This is the whole code. I can't figure out what's wrong. Thanks!!

var results = [SearchResult]() var indexN = 0 var addStudent = false var searchController: UISearchController!  var filteredTableData = [String]() var resultSearchController = UISearchController()   @IBAction func AddStudentButton(_ sender: Any) {     addStudent=true     performSegue(withIdentifier: "detailSegue", sender: self) }  @IBAction func refreshButton(_ sender: Any) {     refreshTable() }  override func viewDidLoad() {     super.viewDidLoad()     // Do any additional setup after loading the view, typically from a nib.      listTableView.delegate = self     listTableView.dataSource = self      listTableView.reloadData()      jsonParser()      self.resultSearchController = ({          let controller = UISearchController(searchResultsController: nil)          controller.searchResultsUpdater = self          controller.dimsBackgroundDuringPresentation = true          controller.searchBar.sizeToFit()            self.listTableView.tableHeaderView = controller.searchBar            return controller      })()     self.listTableView.reloadData()   }  /* func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {     return 1 } */  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {      if (self.resultSearchController.isActive) {          return self.filteredTableData.count      }      else {          return self.results.count      }      // return self.results.count }  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {     let cell:UITableViewCell = UITableViewCell(style:UITableViewCellStyle.subtitle, reuseIdentifier: "cell")     //cell.textLabel!.text = self.results[indexPath.row].firstName + " " + results[indexPath.row].lastName     //return cell     // let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)        if (self.resultSearchController.isActive) {          cell.textLabel?.text = filteredTableData[indexPath.row]            return cell      }      else {          cell.textLabel?.text = self.results[indexPath.row].firstName + " " + results[indexPath.row].lastName         return cell      }  }  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {     indexN = indexPath.row     addStudent=false     performSegue(withIdentifier: "detailSegue", sender: self) }  func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {     return true }  func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {     if (editingStyle == UITableViewCellEditingStyle.delete) {         // handle delete (by removing the data from your array and updating the tableview)         Delete(studentID: self.results[indexN].studentID)         refreshTable()     } }  func numberOfSections(in tableView: UITableView) -> Int {      return 1  }     override func didReceiveMemoryWarning() {     super.didReceiveMemoryWarning()     // Dispose of any resources that can be recreated. }  func jsonParser() {     let urlPath = "http://csmadison.dhcp.bsu.edu/~vjtanksale/cs320/selectstudents.php"     guard let endpoint = URL(string: urlPath) else {         print("Error creating endpoint")         return     }     let request = URLRequest(url: endpoint)     URLSession.shared.dataTask(with: request) { (data, response, error) in         do {             guard let data = data else {                 return             }             guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [[String:AnyObject]] else {                 print("No idea")                 return             }              for result in json {                 if let student = SearchResult(json: result) {                     self.results.append(student)                 }             }             self.grabData()         } catch let error as NSError {             print(error.debugDescription)         }         }.resume() }  func grabData() {     DispatchQueue.main.async {         self.listTableView.reloadData()     } }  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {     if(addStudent==false){         let newVC: DetailViewController = segue.destination as! DetailViewController         newVC.result = results[indexN]         newVC._label1 = results[indexN].studentID         newVC._label2 = results[indexN].lastName         newVC._label3 = results[indexN].firstName         newVC._label4 = results[indexN].major         newVC._label5 = results[indexN].year         newVC._label6 = results[indexN].gpa     }     else if(addStudent==true){         let newVC: DetailViewController = segue.destination as! DetailViewController         newVC.addStudent=true     }  }  func Delete(studentID: String) {     let request = NSMutableURLRequest(url: NSURL(string: "http://csmadison.dhcp.bsu.edu/~vjtanksale/cs320/deletestudents.php")! as URL)     request.httpMethod = "POST"     let postString = "StudentId="+studentID     request.httpBody = postString.data(using: String.Encoding.utf8)      let task = URLSession.shared.dataTask(with: request as URLRequest) {         data, response, error in          if error != nil {             print("error=\(error)")             return         }          print("response = \(response)")          let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)         print("responseString = \(responseString)")     }     task.resume() }  func refreshTable(){     results.removeAll()     self.listTableView.reloadData()     jsonParser()     self.listTableView.reloadData() }  func updateSearchResults(for searchController: UISearchController)  {      filteredTableData.removeAll(keepingCapacity: false)        let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %@", searchController.searchBar.text!)      let array = (results as NSArray).filtered(using: searchPredicate)      filteredTableData = array as! [String]        self.listTableView.reloadData()  } 

}

回答1:

You're getting this error because you're trying to use a CONTAINS predicate on SearchResult objects, which aren't collections with a defined notion of CONTAINS. This error occurs at runtime because NSPredicate parses and processes its string at runtime. It's MUCH more preferable to use native swift facilities for this:

let searchTerm = searchController.searchBar.text!  let array = results.filter { result in     return result.studentID.contains(searchTerm) ||            result.something.contains(searchTerm) // and so on... } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!