我试图在我的iOS应用中进行智能搜索,以便当用户在UISearchBar中键入字符时,结果会在搜索栏下方的表格视图中自动更新。由于某些原因,当我在搜索栏中键入字符时,不会调用带有textDidChange的searchBar函数。键入2个字符后调用。因此,我的搜索结果总是比实际在搜索栏中输入的内容落后1步。而且似乎search()函数每次被调用两次。有任何想法吗?
//FUNC: search func search(searchText: String? = nil){ if searchText == nil || searchText == "" { println("No users found.") } else { var query = PFUser.query() //MAKE CASE INSENSTIVE query!.whereKey("username", containsString: searchText!) query!.findObjectsInBackgroundWithBlock { (results, error) -> Void in if error != nil { println(error) } else { if let res = results { self.data = res as? [PFUser] } } } } self.tableView.reloadData() } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell let user = data[indexPath.row] as! PFUser let username = user.username println(username) cell.textLabel?.text = username return cell } func searchBar(searchBar: UISearchBar, textDidChange searchText: String) { search(searchText: searchText) searchActive = false; }
您将需要实现UISearchResultsUpdating协议来实现此目的。它使用UISearchController(在iOS 8中引入),该UISearchController必须以编程方式添加,而不是通过故事板添加,但是不用担心,这很简单。
这应该为您完成工作
干杯,罗素
class YourTableViewController: UITableViewController, UISearchBarDelegate, UISearchResultsUpdating { var searchUsers: [PFUser] = [PFUser]() var userSearchController = UISearchController() var searchActive: Bool = false // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() self.userSearchController = UISearchController(searchResultsController: nil) self.userSearchController.dimsBackgroundDuringPresentation = true // This is used for dynamic search results updating while the user types // Requires UISearchResultsUpdating delegate self.userSearchController.searchResultsUpdater = self // Configure the search controller's search bar self.userSearchController.searchBar.placeholder = "Search for a user" self.userSearchController.searchBar.sizeToFit() self.userSearchController.searchBar.delegate = self self.definesPresentationContext = true // Set the search controller to the header of the table self.tableView.tableHeaderView = self.userSearchController.searchBar } // MARK: - Parse Backend methods func loadSearchUsers(searchString: String) { var query = PFUser.query() // Filter by search string query.whereKey("username", containsString: searchString) self.searchActive = true query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]?, error: NSError?) -> Void in if (error == nil) { self.searchUsers.removeAll(keepCapacity: false) self.searchUsers += objects as! [PFUser] self.tableView.reloadData() } else { // Log details of the failure println("search query error: \(error) \(error!.userInfo!)") } self.searchActive = false } } // MARK: - Search Bar Delegate Methods func searchBarSearchButtonClicked(searchBar: UISearchBar) { // Force search if user pushes button let searchString: String = searchBar.text.lowercaseString if (searchString != "") { loadSearchUsers(searchString) } } func searchBarCancelButtonClicked(searchBar: UISearchBar) { // Clear any search criteria searchBar.text = "" // Force reload of table data from normal data source } // MARK: - UISearchResultsUpdating Methods // This function is used along with UISearchResultsUpdating for dynamic search results processing // Called anytime the search bar text is changed func updateSearchResultsForSearchController(searchController: UISearchController) { let searchString: String = searchController.searchBar.text.lowercaseString if (searchString != "" && !self.searchActive) { loadSearchUsers(searchString) } } // MARK: - Table view data source override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if (self.userSearchController.active) { return self.searchUsers.count } else { // return whatever your normal data source is } } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell = tableView.dequeueReusableCellWithIdentifier("userCell") as! UserCell if (self.userSearchController.active && self.searchUsers.count > indexPath.row) { // bind data to the search results cell } else { // bind data from your normal data source } return cell } // MARK: - UITableViewDelegate override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { tableView.deselectRowAtIndexPath(indexPath, animated: true) if (self.userSearchController.active && self.searchUsers.count > 0) { // Segue or whatever you want } else { // normal data source selection } } }