0

I am trying to create a search filter using a tableview with multiple sections and get the error 'Cannot assign value of type '[String]' to type 'String' on the line "cell?.textLabel?.text = self.searchArray[indexPath.row].rowTitles". How do I fix this? The ultimate goal is to be able to display the rowTitles in sections of the tableview. Here is my code.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var searchBar: UISearchBar!
    @IBOutlet weak var tableView: UITableView!

    let dataArray = [(sectionTitle: "section 1", rowTitles: ["row 1", "row 2"]),
    (sectionTitle: "section 2", rowTitles: ["row 1", "row 2", "row 3"]),
    (sectionTitle: "section 3", rowTitles: ["row 1"]),
    ]
    var searchArray = [(sectionTitle: String, rowTitles: [String])]()
    var searching = false

    override func viewDidLoad() {
        super.viewDidLoad()

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

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searching {
            return searchArray.count
        } else {
            return dataArray.count
        }
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "searchCell")
        if searching {
            cell?.textLabel?.text = self.searchArray[indexPath.row].rowTitles
        } else {
            cell?.textLabel?.text = self.dataArray[indexPath.row].rowTitles
        }
        return cell!
    }
    func numberOfSections(in tableView: UITableView) -> Int {
        return self.dataArray.count
    }
}


extension ViewController: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        searchArray =  dataArray.filter({$0.sectionTitle.lowercased().contains(searchBar.text!.lowercased())} )
        searching = true
        tableView.reloadData()
    }
}
1
  • 1
    Also you should avoid force-unwrapping return cell! Commented May 19, 2020 at 19:49

3 Answers 3

1

First of all do not use tuples as data source array. Use a struct.

There are many issues. Basically you are not considering the section information at all. You have to get the current section with indexPath.section and the current row with indexPath.row

Replace numberOfRowsInSection with

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if searching {
        return searchArray[section].rowTitles.count
    } else {
        return dataArray[section].rowTitles.count
    }
}

and cellForRow with

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "searchCell", for: indexPath)
    if searching {
        cell.textLabel?.text = self.searchArray[indexPath.section].rowTitles[indexPath.row]
    } else {
        cell.textLabel?.text = self.dataArray[indexPath.section].rowTitles[indexPath.row]
    }
    return cell
}
Sign up to request clarification or add additional context in comments.

Comments

0

self.searchArray[indexPath.row].rowTitles is an array of Strings, not a String.

cell.textLabel.text is a String value, therefore you cannot assign the first to the latter.

I think you should use one of the strings inside rowTitles and assign that to the textLabel.text

Hope this helped!

Comments

0

Because cell?.textLabel?.text expects String type whereas you are passing an array (rowTitles) of Strings to it.

Try to pass an string (based on your requirement) from your array (rowTitles) and it will be gone.

if searching {
    cell?.textLabel?.text = self.searchArray[indexPath.row].rowTitles[0]
} else {
    cell?.textLabel?.text = self.dataArray[indexPath.row].rowTitles.first[1]
}

Comments

Your Answer

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