I’m implementing a search bar with an UISearchController within a sectioned table. So far so good.
The main issue is that when the the filtered results come along, it’s a whole new table with no sections and fewer rows.
When selecting the row, I perform a segue to that position in the array, but the detailed view is expecting that exact row or index from the main array, which I can’t get from the filtered array of objects, which may be [0] [1] [2] in 300 elements.
I guess I can compare the selected object with the main array and assuming there’s no duplicates, get the index from there and pass it over… But these seems pretty inefficient to me.
Apple does something similar (I unfortunately don’t know how) when filtering Contacts, in the Contacts App. How they pass the contact object? That’s pretty much my goal.
Here I let you a snippet of what I’m doing:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if(self.resultSearchController.active) {
customerAtIndex = indexPath.row // Issue here
performSegueWithIdentifier("showCustomer", sender: nil)
}
else {
customerAtIndex = returnPositionForThisIndexPath(indexPath, insideThisTable: tableView)
performSegueWithIdentifier("showCustomer", sender: nil)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showCustomer" {
if let destination = segue.destinationViewController as? CustomerDetailViewController {
destination.newCustomer = false
destination.customer = self.customerList[customerAtIndex!]
destination.customerAtIndex = self.customerAtIndex!
destination.customerList = self.customerList
}
}
}
You can either do in another way, it a trick, but it works. First change your didSelectRowAtIndexPath as below:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var object :AnyObject?
if(self.resultSearchController.active) {
object = filteredArray[indexPath.row]
}
else {
object = self.customerList[indexPath.row]
}
performSegueWithIdentifier("showCustomer", sender: object)
}
Now, in prepareForSegue, get back the object and send it to your detailed view controller
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showCustomer" {
if let destination = segue.destinationViewController as? CustomerDetailViewController {
destination.newCustomer = false
destination.customer = sender as! CustomerObject
destination.customerAtIndex = self.customerList.indexOfObject(destination.customer)
destination.customerList = self.customerList
}
}
}
Here's the trick I used in my code, I basically load the tableView from the filteredObjects array so then indexPath is always correct:
var selectedObject: Object?
private var searchController: UISearchController!
private var allObjects: [Object]? {
didSet {
filteredObjects = allObjects
}
}
private var filteredObjects: [Object]? {
didSet {
NSOperationQueue.mainQueue().addOperationWithBlock {
self.tableView.reloadData()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
loadData { objects in
self.allObjects = objects
}
}
// MARK:- UITableView
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredObjects?.count ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = filteredObjects?[indexPath.row].name
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedObject = filteredObjects?[indexPath.row]
}
// MARK:- UISearchBarDelegate
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if !searchText.isEmpty {
filteredObjects = allObjects?.filter{ $0.name.lowercaseString.rangeOfString(searchText.lowercaseString) != nil }
} else {
filteredObjects = allObjects
}
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