I've been trying to do SearchBar on UITableView with checkmark. Where user can checkmark only one at a time. I managed to do checkmark and search. But when I search and checkmark on the search result, that is where it started to fail
import UIKit
class CandyTableViewController : UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate {
var lastSelectedIndexPath = NSIndexPath(forRow: 0, inSection: 0)
var candies = [Candy]()
var mySelected=String()
var filteredCandies = [Candy]()
override func viewDidLoad() {
self.candies = [Candy(category:"Chocolate", name:"chocolate Bar"),
Candy(category:"Chocolate", name:"chocolate Chip"),
Candy(category:"Chocolate", name:"dark chocolate"),
Candy(category:"Hard", name:"lollipop"),
Candy(category:"Hard", name:"candy cane"),
Candy(category:"Hard", name:"jaw breaker"),
Candy(category:"Other", name:"caramel"),
Candy(category:"Other", name:"sour chew"),
Candy(category:"Other", name:"gummi bear")]
mySelected=candies[lastSelectedIndexPath.row].name
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.searchDisplayController!.searchResultsTableView {
return self.filteredCandies.count
} else {
return self.candies.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
cell.accessoryType = .Checkmark
var candy : Candy
if tableView == self.searchDisplayController!.searchResultsTableView {
candy = filteredCandies[indexPath.row]
} else {
candy = candies[indexPath.row]
}
if mySelected==candy.name {
cell.accessoryType = .Checkmark
lastSelectedIndexPath=indexPath
} else {
cell.accessoryType = .None
}
cell.textLabel.text = candy.name
return cell
}
func filterContentForSearchText(searchText: String, scope: String = "All") {
self.filteredCandies = self.candies.filter({( candy : Candy) -> Bool in
var categoryMatch = (scope == "All") || (candy.category == scope)
var stringMatch = candy.name.rangeOfString(searchText)
return categoryMatch && (stringMatch != nil)
})
}
func searchDisplayController(controller: UISearchDisplayController!, shouldReloadTableForSearchString searchString: String!) -> Bool {
let scopes = self.searchDisplayController!.searchBar.scopeButtonTitles as [String]
let selectedScope = scopes[self.searchDisplayController!.searchBar.selectedScopeButtonIndex] as String
self.filterContentForSearchText(searchString, scope: selectedScope)
return true
}
func searchDisplayController(controller: UISearchDisplayController!,
shouldReloadTableForSearchScope searchOption: Int) -> Bool {
let scope = self.searchDisplayController!.searchBar.scopeButtonTitles as [String]
self.filterContentForSearchText(self.searchDisplayController!.searchBar.text, scope: scope[searchOption])
return true
}
func searchDisplayController(controller: UISearchDisplayController, willHideSearchResultsTableView tableView: UITableView) {
self.tableView.reloadData()
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
if indexPath.row != lastSelectedIndexPath?.row {
if let lastSelectedIndexPath = lastSelectedIndexPath {
let oldCell = tableView.cellForRowAtIndexPath(lastSelectedIndexPath)
oldCell?.accessoryType = .None
}
let newCell = tableView.cellForRowAtIndexPath(indexPath)
newCell?.accessoryType = .Checkmark
lastSelectedIndexPath = indexPath
mySelected = newCell?.textLabel.text ?? ""
}
if candies[indexPath.row].name != candies[lastSelectedIndexPath.row].name {
let oldCell = tableView.cellForRowAtIndexPath(lastSelectedIndexPath)
oldCell?.accessoryType = .None
}
let newCell = tableView.cellForRowAtIndexPath(indexPath)
newCell?.accessoryType = .Checkmark
lastSelectedIndexPath = indexPath
mySelected = newCell?.textLabel.text ?? ""
}
}
I want it to be able to checkmark after search. And keep it that way when return back to full list. Please help, I've been tried to solve this for few days already.
Update: I managed to do as intended. But believe the codes can be more simpler than this
You have a bug to fix, then a couple changes to make the selection from the search results show up in the regular table view.
First, the bug - in
tableView:didSelectRowAtIndexPath:
, you're settingmyselected
like this:That works fine in the regular table view, but in the search results,
indexPath.row
isn't pointing at the right member of thecandies
array. Since you're keeping track by the name of the candy, just grab the name back out of the selected row:If you run your code with this change, you won't see any difference, because you aren't reloading the main table view after the search. To do that, implement the delegate method
searchDisplayController:willHideSearchResultsTableView:
:Almost there! When configuring your cells for the table view, you're adding a checkmark to the current cell, but aren't clearing it from the others. Change your code slightly to this: