iOS - UISearchBar动态搜索结果快速输入时不起作用(swift)

问题描述:

我想要的是一个搜索栏,当用户输入每个字符到搜索栏时,用户名被更新。当用户删除(退格)搜索栏中的所有字符,即搜索栏为空时,我希望tableview不显示用户名并且为空。iOS - UISearchBar动态搜索结果快速输入时不起作用(swift)

我有一个半功能的UISearchbar,用于搜索用户名(解析后端)。当我在搜索栏中逐字输入字符时,它工作的很好。

但是,当我快速输入时,搜索结果有点偏离 - 它显示了我以前输入的字符的用户名。例如:如果我很快输入'nik',它仍然会显示我用户名'ni'。另外,当我退格时,直到搜索栏中没有字符,它仍然显示我某些用户名。

再说一次,当我慢慢输入字符时,它可以正常工作,但我觉得它效率不高。我尝试了各种各样的东西,但目前为止没有任何效果。我已经添加了下面的相关代码,让我知道你是否需要更多信息。

// called when keyboard search button pressed 
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { 

    let searchString = searchBar.text; 

    if (searchString != "") { 
     //do load users 
     loadUsers(searchText: searchString!); 
     print("called from searchBarSearchButtonClicked"); 
    } 

} 

// called when cancel button pressed 
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { 

    searchBar.text = ""; 

    //hide tableview maybe?! 
    //searchTableView.isHidden = true; 

} 

func updateSearchResults(for searchController: UISearchController) { 
    let searchString: String = (searchController.searchBar.text)!; 


    /*if (searchString == "" && !searchActive) { 
     searchResults.removeAll(keepingCapacity: false); 
     searchTableView.reloadData(); 
     print("test"); 
    }*/ 

    if (searchString != "" && !self.searchActive) { 
     loadUsers(searchText: searchString); 
     print("called from updateResults"); 
    } 

    if (searchString == "") { 
     searchResults.removeAll(keepingCapacity: false); 
     searchTableView.reloadData(); 
     print("test"); 
    } 
} 


func loadUsers(searchText: String) { 

    if(searchText != "") { 


     let usernameQuery = PFUser.query(); 
     //usernameQuery?.whereKey("username", equalTo: searchText); 
     usernameQuery?.whereKey("username", contains: searchText.lowercased()); 


     let fbUsername = PFUser.query(); 
     fbUsername?.whereKey("username", contains: searchText); 


     let firstnameQuery = PFUser.query(); 
     //firstnameQuery?.whereKey("last_name", equalTo: searchText) 
     firstnameQuery?.whereKey("last_name", contains: searchText); 


     let lastnameQuery = PFUser.query(); 
     //lastnameQuery?.whereKey("first_name", equalTo: searchText); 
     lastnameQuery?.whereKey("first_name", contains: searchText); 


     let query = PFQuery.orQuery(withSubqueries: [usernameQuery!,fbUsername!, firstnameQuery!, lastnameQuery!]); 

     searchActive = true; 

     query.findObjectsInBackground { (objects, error) in 

      if error != nil { 

       print("There was an error getting userlist"); 

      } 

      else { 

       if let object = objects { 

        self.searchResults.removeAll(keepingCapacity: false); 

        for object in objects! { 

         let user = object.object(forKey: "username") as! String; 
         self.searchResults.append(user); 

        } 

        //self.searchTableView.reloadData(); 


        DispatchQueue.main.async { 

        self.searchTableView.reloadData(); 

        //self.userSearchController.searchBar.resignFirstResponder(); 

        } 

       } 

      } 

      self.searchActive = false; 

     } 
    } 

} 


override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
} 


public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 

    if(userSearchController.isActive) { 

     print(searchResults.count); 
     return searchResults.count; 

    } 

    return 0; 
} 


public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath); 

    if(self.userSearchController.isActive && searchResults.count > indexPath.row) { 

     print(searchResults[indexPath.row]); 
     cell.textLabel?.text = searchResults[indexPath.row]; 

    } 

    return cell; 

} 




/* 
public func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool { 
    return true; 
} 

public func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool { 
    return true; 
} 



func searchBarTextDidEndEditing(_ searchBar: UISearchBar) { 

     //loadUsers(searchText: (searchBar.text)!); 
} */ 


func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { 

    if (searchBar.text != "") { 
     NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(loadUsers(searchText:)), object: searchBar.text! as String); 


     perform(#selector(loadUsers(searchText:)), with: searchBar.text! as String, afterDelay: 0.50); 


     print("called from textDidChange"); 

    } 
    if (searchBar.text == "") { 

     searchResults.removeAll(keepingCapacity: false); 
     searchTableView.reloadData(); 
     print("test2"); 
    } 

} 

我用Timer解决了这个问题。在调用你的函数之前,下面的代码等待一秒钟。如果在那一秒内发生文本更改,则它将使先前的计划的计时器无效并且仅执行第二个计时器。您可以通过在您的功能中打印搜索文本来检查。

var timer: Timer? 

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { 
     timer?.invalidate() //cancels out previous Timers 
     timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(myFunctionThatDoesServerSearch), userInfo: nil, repeats: false) 
    }