Контроллер поиска — проблемы с использованием NSPredicate с моделью

У меня есть табличное представление, которое получает данные json с моего сервера. Теперь я хочу добавить панель поиска, используя SearchContoller. Ячейки (кастомные) правильно отображаются перед поиском:

введите здесь описание изображения

но когда я начинаю печатать, ничего не отображается. Вот код:

МОДЕЛЬ

import Foundation
class PreviousLocations:NSObject{

 let locationId: String?
 let locationName: String?
 let locationCity:String?
 let locationCountry:String?
 let locationLatitude:String?
 let locationLongitude:String?
 let sport:String?


  init(dictionary:NSDictionary) {
    locationId = dictionary["locationId"]    as? String
    locationName = dictionary["locationName"]    as? String
    locationCity = dictionary["locationCity"]    as? String
    locationCountry = dictionary["locationCountry"]    as? String
    sport = dictionary["sport"]    as? String
    locationLatitude = dictionary["locationLatitude"]    as? String
    locationLongitude = dictionary["locationLongitude"]    as? String

   }
}

Затем в PreviousLocationsViewControllors

 var previousLocation = [PreviousLocations]()
 var filteredPreviousLocations  = [PreviousLocations]()

 fun tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {  
          if section == 0 {     
              return 1
          }

          if section == 1{

              if (self.searchController.active) {
                 return filteredPreviousLocations.count     
              }else{

                 return previousLocation.count
              }

        }
        return 1
    }


func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    return 2
 }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{

       if indexPath.section == 0{

        let addLocationCell = self.tableView.dequeueReusableCellWithIdentifier("addLocationCell", forIndexPath: indexPath) 

        addLocationCell.textLabel?.text = "Add Location"
        return addLocationCell

    }else{

    var locCells:PreviousLocationsTableCell
    let locations : PreviousLocations

        if (self.searchController.active) {

        locCells =  self.tableView.dequeueReusableCellWithIdentifier("previousLocationCell") as! PreviousLocationsTableCell

            locations = filteredPreviousLocations[indexPath.row]
            locCells.useLocations(locations)

         }else{

           locCells = self.tableView.dequeueReusableCellWithIdentifier("previousLocationCell", forIndexPath: indexPath) as! PreviousLocationsTableCell


            locations = previousLocation[indexPath.row]
            locCells.useLocations(locations)

    }

    return locCells
    }
}


//MARK: - Search


func updateSearchResultsForSearchController(searchController: UISearchController)
{

    filteredPreviousLocations.removeAll(keepCapacity: false)
    let searchPredicate = NSPredicate(format: "SELF.locationName == %@", searchController.searchBar.text!)
    let array  = (previousLocation as NSArray).filteredArrayUsingPredicate(searchPredicate)
    print(array)
    filteredPreviousLocations = array as! Array
    self.tableView.reloadData()
}

и пользовательская ячейка

import UIKit
import QuartzCore


class PreviousLocationsTableCell: UITableViewCell {


@IBOutlet weak var conteningView: UIView!
@IBOutlet weak var locatioNameLabel: UILabel!
@IBOutlet weak var locationCityLabel: UILabel!
@IBOutlet weak var sportImage: UIImageView!


func useLocations(location:PreviousLocations) {



    conteningView.layer.masksToBounds = true
    conteningView.exclusiveTouch = false
    // Fill in the data
    locatioNameLabel.text = location.locationName
    locationCityLabel.text = location.locationCity

    let imageSport = UIImage(named: "\(location.sport!).png")
    sportImage.image = imageSport

    func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }


 }

  }

Если я попытаюсь изменить это

    `filteredPreviousLocations = array as! Array`

в это

    `filteredPreviousLocations = array as! [String]`

как описано в этом этом руководстве, получаю ошибку Cannot assign a value of type '[String]' to a value of type '[PreviousLocations]'


person Mat    schedule 18.10.2015    source источник


Ответы (1)


Типы свойств четко определены как [PreviousLocations], поэтому вам не нужно приводить типы, кроме как в строке фильтра. Строка формата должна быть locationName == %@.

func updateSearchResultsForSearchController(searchController: UISearchController)
{
  let searchPredicate = NSPredicate(format: "locationName == %@", searchController.searchBar.text!)
  filteredPreviousLocations = (previousLocation as NSArray).filteredArrayUsingPredicate(searchPredicate)
  self.tableView.reloadData()
}

В качестве альтернативы вы можете фильтровать с помощью функции Swift filter.

func updateSearchResultsForSearchController(searchController: UISearchController)
{
  filteredPreviousLocations = previousLocation.filter { $0.locationName == searchController.searchBar.text!}
  self.tableView.reloadData()
}

Так как в обеих функциях массив filteredPreviousLocations задан четко, вызов removeAll тоже не нужен

Изменить: чтобы получить результаты поиска до ввода полного имени, вы должны отфильтровать частичную строку, а не полное имя местоположения.

func updateSearchResultsForSearchController(searchController: UISearchController)
{
  filteredPreviousLocations = previousLocation.filter { $0.locationName.rangeOfString(searchController.searchBar.text!, options: [.AnchoredSearch, .CaseInsensitiveSearch, .DiacriticInsensitiveSearch]) != nil}
  self.tableView.reloadData()
}
person vadian    schedule 18.10.2015
comment
@ В первом решении я получаю ` Значение типа '[PreviousLocations]' не имеет члена 'filteredArrayUsingPredicate'`, а во втором я все еще получаю пустую таблицу, когда начинаю печатать - person Mat; 18.10.2015
comment
спасибо, но теперь `Невозможно присвоить значение типа '[AnyObject]' значению типа '[PreviousLocations]'` В учебнике отфильтрованный массив объявлен как var filteredTableData = [String](), но если я это сделаю, я не смогу этого сделать `locations = filteredPreviousLocations [indexPath.row] locCells.useLocations(местоположения)` - person Mat; 18.10.2015
comment
после вашего последнего редактирования я получаю Value of type 'PreviousLocations' has no member 'locationNamerangeOfString' - person Mat; 18.10.2015
comment
Я пропустил точку перед rangeOfString. Отфильтрованный массив должен иметь тот же тип, что и основной массив - person vadian; 18.10.2015