Search code examples
arraysswiftuitableviewuisearchbaruisearchcontroller

Add A SearchBar to a uitableview confronts an error in filter process


I am following a tutorial about how to add a search-bar for ui table view to my swift project ,I followed this link ,https://www.youtube.com/watch?v=XtiamBbL5QU and I am stuck in the half of code. In this line of my project

 self.countries.filter { (Country:String) -> Bool in
            <#code#>
        }

I have this Error String' is not convertible to 'HistoryViewController.Country HistoryViewController is the name of my table view controller. and the only thing which is different in my project with tutorial is that I have an array called Countries which it includes rows of dictionaries. I am going to post my other parts of codes here

import UIKit

class HistoryViewController: UITableViewController , UISearchResultsUpdating {


    var searchController : UISearchController!
    var resultsController = UITableViewController()


    var myPlistArray: [String] = []

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
    {
        return 115 //or whatever you need
    }

    struct Country : Decodable {
        let flagEmoji, Abb, countryName, pName : String

        private enum CointryKeys : String, CodingKey { case flagEmoji, Abb, countryName, pName }
    }

    var countries = [Country]()

    func updateSearchResults(for searchController: UISearchController) {
        //Filter through currencies

        self.countries.filter { (Country:String) -> Bool in
            <#code#>
        }

        // Update the results Table View

    }




    override func viewDidLoad() {
        super.viewDidLoad()


        self.searchController = UISearchController(searchResultsController: self.resultsController)
        self.tableView.tableHeaderView = self.searchController.searchBar
        self.searchController.searchResultsUpdater = self

        let url = Bundle.main.url(forResource: "Curr", withExtension: "plist")!
        let data = try! Data(contentsOf: url)


        do {

            countries = try PropertyListDecoder().decode([Country].self, from: data)
        } catch {
            // Handle error
            print(error)
        }
        print(countries)
        print("countries.count:", countries.count)


    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return countries.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        print("hiiii")

        let cell = tableView.dequeueReusableCell(withIdentifier: "historyCell", for: indexPath) as! TableViewCellforHistory

        // Configure the cell...


        cell.lblCellHistory.text = countries[indexPath.row].countryName
        cell.lblEmoji.text = countries[indexPath.row].flagEmoji
        cell.lblCurrencyName.text = countries[indexPath.row].pName

        return cell
    }
 }

Solution

  • Change the filter closure as below because countries is an array of Country but you are treating it as String(by doing Country: String) ,

     self.countries.filter { country -> Bool in
          return country.countryName == "Pakistan"
     }
    

    or

     self.countries.filter { (country: Country) -> Bool in
          return country.countryName == "Pakistan"
     }
    

    Or simply,

    self.countries.filter { $0.countryName == "Pakistan" }
    

    Edit

    To get the list of country names (i.e, [String]), you have to use map on filtered result as below,

    let filteredCountryNames = self.countries.filter { (country: Country) -> Bool in
              return country.countryName == "Pakistan"
         }.map { $0.countryName }