问题
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 :)
回答1:
You can add a tap gesture recognizer to your view that when fired would
- resign the search bar responder
- convert the tap location to a point in you table view
- get the cell that tap location
- 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)
}
}
回答2:
Swift 4+ or iOS 10+
1- Remove searching overlay on viewDidLoad or elsewhere.
searchController.obscuresBackgroundDuringPresentation = false
2- In TableView didSelectRowAt delegate add this line.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
searchController.isActive = false
<your code>
}
..Done..
Note: with iOS 11+ if you use the SearchController in the navigation item, you will not have this problem. If you present the ViewController with the searchController, just add a new navigation with your ViewController. And present the new navigation instead.
UINavigationController(rootViewController: ViewControllerWithSearchBar)
来源:https://stackoverflow.com/questions/40178206/double-tap-necessary-to-select-tableview-item-with-search-bar