Reputation: 1619
I've been trying to implement a UISearchController in an app, and as reference, I was following this tutorial. The tutorial covered a bit more than I needed (like scope), so I only skimmed it, but when I ran my test app, the search didn't work. When I typed in the search bar, it only filtered results for the first character I typed in, regardless of whether I pressed "search" or not. For example, if I typed in "dolphin", it would only show results that contained "d". By printing inside updateSearchResultsForSearchController
, I confirmed that it was only called once.
However, if I deleted everything in the search bar, the results would go back to being unfiltered, and if I typed in something again, it would (again) only filter for the first character.
I also tried the workaround suggested here, but the issue still persisted. This is my code:
class SearchController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {
let data = [
"bottlenose dolphin": 111,
"manta ray": 172,
"humphead wrasse": 388,
"Commerson's dolphin": 19
// etc.
]
var results = [String: Int]()
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
searchController.searchBar.delegate = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.active && searchController.searchBar.text != "" {
return results.count
} else {
return data.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
if searchController.active && searchController.searchBar.text != "" {
let index = results.startIndex.advancedBy(indexPath.row)
cell.textLabel!.text = results.keys[index]
} else {
let index = data.startIndex.advancedBy(indexPath.row)
cell.textLabel!.text = data.keys[index]
}
return cell
}
func search(searchText: String) {
let temp = data.filter({(element: (String, Int)) -> Bool in
return element.0.lowercaseString.containsString(searchText.lowercaseString)
})
for element in temp { results[element.0] = element.1 }
tableView.reloadData()
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
updateSearchResultsForSearchController(searchController)
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
search(searchController.searchBar.text!)
}
}
There's the chance that I missed a step when skimming the tutorial, but I've looked through it several more times to no avail. How can I make the search work properly?
Edit: I also just noticed that sometimes the search would pop up results that didn't even contain the first character of the query. For example, using a different set of data, searching "J" popped up "Silicon Valley"...
Upvotes: 0
Views: 466
Reputation: 2459
You forget to remove previous results
.
func search(searchText: String) {
let temp = data.filter({(element: (String, Int)) -> Bool in
return element.0.lowercaseString.containsString(searchText.lowercaseString)
})
results.removeAll() // clear previous ones
for element in temp { results[element.0] = element.1 }
tableView.reloadData()
}
Upvotes: 1