UISearchController only update when the search button is clicked

I have a UISearchController that is configured to search a very large array of data. Thus, when I type a search string, it takes a very long time to enter my search. It compares the search with all the characters in the search field, which is very slow.

I am wondering how to fix this. My thoughts:

  • performs a search only after the user completes the entry and presses the search button.
  • perform a search in the background thread, freeing up the main thread for keyboard input.

I would like to use method 1 but I cannot figure out how to do this with the new UISearchController.

Below is my relevant project code:

class AirportSearchTBVC: UITableViewController, UISearchResultsUpdating{ var airportData = [Dictionary<String, String>]() var filteredData = [Dictionary<String, String>]() var searchController = UISearchController() override func viewDidLoad() { super.viewDidLoad() searchController = UISearchController(searchResultsController: nil) searchController.searchResultsUpdater = self searchController.dimsBackgroundDuringPresentation = false searchController.searchBar.sizeToFit() tableView.tableHeaderView = searchController.searchBar definesPresentationContext = true searchController.hidesNavigationBarDuringPresentation = false self.tableView.reloadData() } func updateSearchResultsForSearchController(searchController: UISearchController) { filteredData = [] let searchPredicate = NSPredicate(format: "SELF CONTAINS[cd] %@", searchController.searchBar.text!) let array = (airportData as NSArray).filteredArrayUsingPredicate(searchPredicate) filteredData = array as! [Dictionary<String, String>] self.tableView.reloadData() } 

Bonus question If I search for a string, it does not seem to return any results if the string does not fit perfectly. For example: "orida" does not find "Florida." Shouldn't my search predicate find this with CONTAINS?

Update This code almost works, but it basically throws a bunch of stuff into the background thread and then iterates over it. Now the keyboard is lively, but it seems to crash if I quickly change things in the text box, rejecting and entering the search bar again ...

 func updateSearchResultsForSearchController(searchController: UISearchController) { appDel.backgroundThread(background: { self.filteredData.removeAll(keepCapacity: false) let searchPredicate = NSPredicate(format: "SELF CONTAINS[cd] %@", searchController.searchBar.text!) let array = (self.airportData as NSArray).filteredArrayUsingPredicate(searchPredicate) self.filteredData = array as! [Dictionary<String, String>] }, completion: { dispatch_async(dispatch_get_main_queue()) { self.tableView.reloadData() } }); } 

Update 2 After playing a little with this, I was able to make it work pretty well, expecting the searchBar.text> = 3 line to look, and also make sure that the number of characters has not changed in 1 second from updateSearchResultsForSearchController: called. The combination of these functions, as well as the integration of the search button execution command, should solve my problem.

 func updateSearchResultsForSearchController(searchController: UISearchController) { let startCount = searchController.searchBar.text!.length delay(1) { if searchController.searchBar.text!.length >= 3 && searchController.searchBar.text!.length == startCount{ self.view.addSubview(self.progressHud) self.appDel.backgroundThread(background: { self.filteredData.removeAll(keepCapacity: false) let searchPredicate = NSPredicate(format: "SELF CONTAINS[cd] %@", searchController.searchBar.text!) let array = (self.airportData as NSArray).filteredArrayUsingPredicate(searchPredicate) self.filteredData = array as! [Dictionary<String, String>] }, completion: { dispatch_async(dispatch_get_main_queue()) { self.tableView.reloadData() self.progressHud.removeFromSuperview() } }); } } } func delay(delay:Double, closure:()->()) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), closure) } 
+5
source share
2 answers

You can use the delegate method searchBarSearchButtonPressed: to control when the search button is clicked. Set the flag when this delegation method is executed, and then in your searchBarTextDidChange: method searchBarTextDidChange: you can check this flag to see if the search should be performed. Of course, this will only search after the user clicks on the search, and most people expect to see something that happens while typing.

+6
source

If you want to perform a search only when the user clicks the Search button, which seems reasonable and reasonable for a larger and slower set of access data, you can do this as follows:

 class AirportSearchTBVC: UITableViewController, UISearchResultsUpdating{ var airportData = [Dictionary<String, String>]() var filteredData = [Dictionary<String, String>]() var searchController = UISearchController() override func viewDidLoad() { super.viewDidLoad() searchController = UISearchController(searchResultsController: nil) searchController.searchResultsUpdater = self searchController.searchBar.delegate = self searchController.dimsBackgroundDuringPresentation = false searchController.searchBar.sizeToFit() tableView.tableHeaderView = searchController.searchBar definesPresentationContext = true searchController.hidesNavigationBarDuringPresentation = false self.tableView.reloadData() } func searchBarSearchButtonClicked(searchBar: UISearchBar) { filteredData = [] let searchPredicate = NSPredicate(format: "SELF CONTAINS[cd] %@", searchController.searchBar.text!) let array = (airportData as NSArray).filteredArrayUsingPredicate(searchPredicate) filteredData = array as! [Dictionary<String, String>] self.tableView.reloadData() } func updateSearchResultsForSearchController(searchController: UISearchController) { } 

The key differences are setting searchController.searchBar.delegate = self and placing your search code in the searchBarSearchButtonClicked function instead of updateSearchResultsForSearchController, which should now do nothing. I apologize for any errors, I tested this code with Xcode v7.0.1 Objective-C, and then transferred these changes.

+5
source

Source: https://habr.com/ru/post/1233629/


All Articles