Home > OS >  Search through tableview data and handle row selection in Swift
Search through tableview data and handle row selection in Swift

Time:10-05

I have an issue while searching data from tableview. I want to search the data from tableview but stuck up while searching. Below is my code what i have tried. I'm getting issue is cannot assign value of type '[Employee]' to type '[String]' Please help. TIA

var empList: [Employee]!
var searchedText = [String]()

 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        if searching {
            return searchedText.count
        } else {
            return empList?.count  ?? 0
        }
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
        if searching {
            cell.lblTitle.text = searchedText[indexPath.row]
        }else {

            let resObjects = empList?[indexPath.row]

            cell.lblTitle.text = resObjects?.emp_name

        }
return cell
}


 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        
        searchedText = empList.filter{$0.emp_name?.contains(searchText)}
        
// The above line gives me error as, cannot assign value of type '[Employee]' to type '[String]'
        
        searching = true
        tableView.reloadData()
    }
    
    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searching = false
        searchBar.text = ""
        tableView.reloadData()
    }

CodePudding user response:

Replace this:

searchedText = empList.filter{$0.emp_name?.contains(searchText)}

with this:

searchedText = empList.filter{$0.emp_name?.contains(searchText)}.map(\.emp_name) ?? []

The solution is mapping the array of Employee to array of String where the value is the emp_name from Employee model.

P.S: I'm using keyPaths >>> map(.emp_name) because it is shorter.

CodePudding user response:

As already mentioned in the comments it's highly recommended that the data source and the filtered array are of the same type.

And declare both as non-optional empty arrays and give them more meaningful names

var employees = [Employee]()
var filteredEmployees = [Employee]()

Then the data source methods become quite simple

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return searching ? filteredEmployees.count : employees.count
}
    
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {           
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
    let employee = searching : filteredEmployees[indexPath.row] : employees[indexPath.row]
    cell.lblTitle.text = employee.emp_name
    return cell
}

And in textDidChange you have to consider that the user can delete all characters

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText.isEmpty {
       searching = false
       filteredEmployees.removeAll()
    } else {
       searching = true
       filteredEmployees = employees.filter{$0.emp_name.range(of: searchText, options: .caseInsensitive) != nil}
    }
    tableView.reloadData()
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    searchBar.text = ""
}
  • Related