Reputation: 172
What I want to do: I want to filter the TableViewCells that have a text on them, depending on the user input in the UISearchBar.
My problem: I got it to work with simple Cells. But now I use custom ones that I configure with a struct and now I have no clue how to filter them.
Here is my code:
import UIKit
import Firebase
class searchViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
@IBOutlet var searchy: UISearchBar!
@IBOutlet var tabley: UITableView!
var searchingNames = [String()]
var searching = false
var datas = [UserSearch]()
override func viewDidLoad() {
super.viewDidLoad()
tabley.delegate = self
tabley.dataSource = self
searchy.delegate = self
populateSearch()
tabley.register(searchTableViewCell.nib(), forCellReuseIdentifier: searchTableViewCell.identifier)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching == true {
return searchingNames.count
} else{
return datas.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if searching == true {
let post = datas[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: searchTableViewCell.identifier, for: indexPath) as! searchTableViewCell
cell.configure(with: post)
return cell
} else{
let post = datas[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: searchTableViewCell.identifier, for: indexPath) as! searchTableViewCell
cell.configure(with: post)
return cell
}
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchingNames = datas.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()}) // Cannot assign value of type '[UserSearch]' to type '[String]'
// Value of type 'UserSearch' has no member 'lowercased'
searching = true
tabley.reloadData()
}
}
struct UserSearch {
var id: String
var name: String
var pfp: String
}
Upvotes: 1
Views: 123
Reputation: 285069
You have to filter a string property of UserSearch
for example the name
.
And you have to consider that the user clears the search field to reset searching
to false
And there is a more efficient API to check for a substring
First of all the array of the search results must be the same type as the data source array
var searchingNames = [UserSearch]()
Replace textDidChange
with
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.isEmpty {
searchingNames.removeAll()
searching = false
} else {
searchingNames = datas.filter{ $0.name.range(of: searchText, options: [.anchored, .caseInsensitive]) != nil}
searching = true
}
tabley.reloadData()
}
.anchored
searches from the beginning of the string.caseInsensitive
is self-explanatory.PS: In cellForRow
is a mistake. In the searching == true
scope replace
let post = datas[indexPath.row]
with
let post = searchingNames[indexPath.row]
You can even reduce the code to
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let post = searching ? searchingNames[indexPath.row] : datas[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: searchTableViewCell.identifier, for: indexPath) as! searchTableViewCell
cell.configure(with: post)
return cell
}
Upvotes: 2