0

I've got a struct Array that I'm using to populate my tableview. But I am unable to get my searchBar to work correctly. My original searchBar code was created when I was using a more "basic" array. After converting to struct it no longer works. I am getting 3 errors from Xcode. I've identified the errors in the code with // <-- ERROR. Thanks for your help!

import UIKit

struct Material {
    var name : String
    var lbft : String
    var gcm : String
}

class ViewController: UIViewController {

    @IBOutlet weak var searchBar: UISearchBar!

    @IBOutlet var tableView: UITableView!

    let materialData = [
        Material(name: "Acetaminohen Powder, Unmilled",    lbft: "43",    gcm: "0.688794"),
        Material(name: "Acetylene Black, 100% Compressed",    lbft: "35",    gcm: "0.560646"),
        Material(name: "Acetylsalicyic Acid",    lbft: "20",    gcm: "0.320369"),
        Material(name: "Acrylamide",    lbft: "34",    gcm: "0.54463"),
        Material(name: "Acrylic Granules, Coarse",    lbft: "40",    gcm: "0.64"),
        Material(name: "Acrylic Granules, Fine",    lbft: "36",    gcm: "0.58"),
        Material(name: "Acrylonitrile Butadien Styrene (Abs) Resin",    lbft: "50",    gcm: "0.8"),
        Material(name: "Acrylonitrile Butadiene Styrene (Abs) Granules",    lbft: "36",    gcm: "0.58"),
        Material(name: "Activated Alumina",    lbft: "42.5",    gcm: "0.68"),
        Material(name: "Activated Carbon",    lbft: "32.5",    gcm: "0.52"),
        Material(name: "Actylene Black",    lbft: "45.5",    gcm: "0.73"),
        Material(name: "Aero Xanthates",    lbft: "112.5",    gcm: "1.8"),
        Material(name: "Aerolyte",    lbft: "51",    gcm: "0.82"),
        Material(name: "Aerosil, Fumed Silica",    lbft: "32",    gcm: "0.51"),
        Material(name: "Aerosil, Silicon Dioxide",    lbft: "30",    gcm: "0.48"),
        Material(name: "Alaluren",    lbft: "112",    gcm: "1.79")]

    var searchMaterial = [String]()
    var searching = false

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self
    }
}

extension ViewController: UITableViewDelegate {

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

extension ViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searching {
            return searchMaterial.count
        } else {
            return materialData.count
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.numberOfLines = 0
        if searching {
            cell.textLabel?.text = searchMaterial[indexPath.row]
        } else {
            cell.textLabel?.text = materialData[indexPath.row] // <-- ERROR Cannot assign value of type 'Material' to type 'String'
        }
        return cell
    }

}

extension ViewController: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        searchBar.setShowsCancelButton(true, animated: true)
        searchMaterial = materialData.filter({$0.prefix(searchText.count) == searchText}) // <-- ERROR Cannot assign value of type '[Material]' to type '[String]'
                                                                                          // <-- ERROR Value of type 'Material' has no member 'prefix'
        searching = true
        tableView.reloadData()

    }

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.setShowsCancelButton(false, animated: true)
        searching = false
        searchBar.text = ""
        tableView.reloadData()

    }

}



4 Answers 4

2

there is no

materialData[0] etc...

declare your array such as

var searchMaterial:[String] = []

then you can access it like

searchMaterial[indexPath.row]
Sign up to request clarification or add additional context in comments.

Comments

2

1) cell.textLabel?.text = materialData[indexPath.row] the materialData[indexPath.row] will provide you with an object of type Material and not string. Not sure what value you are expecting. But changing it to

materialData[indexPath.row].name

2) searchMaterial = materialData.filter({$0.prefix(searchText.count) == searchText}) // <-- ERROR Cannot assign value of type '[Material]' to type '[String]'

changing to

   var searchMaterial:[Material] = []
   searchMaterial = materialData.filter { $0.name.contains(searchText) }

2 Comments

The first suggestion resolved the associated error. Thank you! The second however returned the same error :/
var searchMaterial:[Material] = [] - change the type of searchMaterial to be consistent with materialData
1

Hi Sean I believe I have solved this,

Everything in your tableView delegate functions are correct

Make sure to create this var at top level

var searchMaterial = [Material]() 

Then add this to your searchBar function:

 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    guard !searchText.isEmpty else {
        searchMaterial = materialData
        tableView.reloadData()
        return // When no items are typed, load your array still 

    }
    searchMaterial = materialData.filter({ (Material) -> Bool in
        Material.title.lowercased().contains(searchText.lowercased())
 })
    searchBar.setShowsCancelButton(true, animated: true)
    searching = true
    tableView.reloadData()

Hope this helped!!!

Comments

0

do you want to search by name? If so, you can fix the second ERROR like this:

searchMaterial = materialData
    .map({ $0.name }) // convert to [String]
    .filter { $0.hasPrefix(searchText) } // search

The first one can be fixed like this:

cell.textLabel?.text = materialData[indexPath.row].name

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.