I have just started to learn swift and i am looking at the tableview and searchbar feature. Below i have my array which is a list of fruits:
var fruits: [[String]] = [["Apple", "Green"],["Pear", "Green"], ["Banana", "Yellow"], ["Orange", "Orange"]]
I have them in a table view with the name of the fruit as the title and the colour as a subtitle. I am trying to use the search bar to filter but i cant seem to get it right. I only want to search for the name of the fruit not the colour.
var filteredFruits = [String]()
var shouldShowSearchResults = false
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredFruits.removeAll()
var i = 0
while i < fruits.count
{
var filteredFruits = fruits[i].filter ({ (fruit: String) -> Bool in
return fruit.lowercased().range(of: searchText.lowercased()) != nil
})
if searchText != ""
{
shouldShowSearchResults = true
if filteredItems.count > 0
{
filteredFruits.append(filteredItems[0])
filteredItems.removeAll()
}
}
else
{
shouldShowSearchResults = false
}
i += 1
}
self.tableView.reloadData()
}
I do get results returned but it mixes up the subtitles and the titles as well as not returning the correct results. Can anyone point me in the right direction?
I do not understand why you iterate over the fruits using some kind of while loop. Instead I would propose you take advantage of a function like:
func filterFruits(searchText: String) -> [[String]] {
guard searchText != "" else {
return fruits
}
let needle = searchText.lowercased()
return fruits.filter {fruitObj in
return fruitObj.first!.lowercased().contains(needle)
}
}
That function returns all fruits that have a name containing the searchText.
filterFruits(searchText: "g")yields[["Orange", "Orange"]]
If you want to search through all attributes use something like:
func filterFruits(searchText: String) -> [[String]] {
guard searchText != "" else {
return fruits
}
let needle = searchText.lowercased()
return fruits.filter {fruitObj in
return fruitObj.contains { attribute in
attribute.lowercased().contains(needle)
}
}
}
filterFruits(searchText: "g")yields[["Apple", "Green"], ["Pear", "Green"], ["Orange", "Orange"]]
To get you on the right track for the future: you should really introduce a Fruit class which holds all relevant information of one specific fruit instance. Then you can use the first function and do something like fruitObj.matches(searchText) where you define a func inside the Fruit class which determines if the fruit matches the search.
How about this?
var filteredFruits = fruits.filter ({ (fruitData: [String]) -> Bool in
let fruit = fruitData[0]
return fruit.lowercased().range(of: searchText.lowercased()) != nil
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With