iosswiftuitableviewsearchuisearchbar

Double tap necessary to select TableView item with Search Bar


I have a UITableView with a search bar as header. I use this function to update my data when the user does a search in the search bar.

func updateSearchResults(for searchController: UISearchController) {

    if let searchText = searchController.searchBar.text {
        if (searchText.characters.count > 0) {
            self.filteredResults  = [];
            self.locationManager?.geocodeAddressString(addressString: searchText, completionHandler: { (results, error) in
                if error == nil && results != nil {
                    self.filteredResults = results!;
                    self.tableView.reloadData();
                }
            });
        }
        else {
            self.filteredResults  = [];
            self.tableView.reloadData();
        }
    }
}

and this function when I select a cell in my UITableView.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    self.delegate?.setCity(city: str);
    self.dismiss(animated: true, completion: nil);
}

Here is my problem : the view controller doesn't dismiss at the first taps on the cell. I taps once, the search bar resign responder. And I need to tap twice for the dismiss to execute.

Here is how I link my tableview and my search bar in viewDidLoad:

// Search Bar componants
self.searchController = UISearchController(searchResultsController: nil);
self.searchController.delegate = self;
self.searchController.searchResultsUpdater = self;
self.searchController.hidesNavigationBarDuringPresentation = false
self.searchController.dimsBackgroundDuringPresentation = false;

self.searchBar = self.searchController.searchBar;
self.searchBar.searchBarStyle = .default;
self.searchBar.delegate = self;
self.searchBar.placeholder = NSLocalizedString("search.city", comment: "search.city").capitalized;

self.tableView = UITableView(frame: CGRect.zero, style: .plain);
self.tableView.translatesAutoresizingMaskIntoConstraints = false;
self.tableView.delegate = self;
self.tableView.backgroundColor = UIColor.white;
self.tableView.dataSource = self;
self.tableView.tableHeaderView = self.searchBar;
self.view.addSubview(self.tableView);

If someone could help me, that would be great :)


Solution

  • You can add a tap gesture recognizer to your view that when fired would

    1. resign the search bar responder
    2. convert the tap location to a point in you table view
    3. get the cell that tap location
    4. manually call didSelectRowAt which isn't the "best" solution but for demonstration purposes.

    Here is how it looks implemented:

    override func viewDidLoad() {
            super.viewDidLoad()
    
            // Add a tap gesture to our view
            let gesture = UITapGestureRecognizer(target: self, action: #selector(TestTableViewController.didTap(_:)))
            self.view.addGestureRecognizer(gesture)
        }
    
        // Called when the tap gesture fires
        func didTap(gesture: UITapGestureRecognizer) {
    
            // We get rid of our keyboard on screen
            searchBar.resignFirstResponder()
    
            // Find the location of the touch relative to the tableView
            let touch = gesture.locationInView(self.tableView)
    
            // Convert that touch point to an index path
            if let indexPath = tableView.indexPathForRowAtPoint(touch) {
    
                // Here I am just calling the delegate method directly which you shouldn't do.
                // You should just do whatever you want to do with the indexPath here.
                tableView(tableView, didSelectRowAtIndexPath: indexPath)
            }
        }