我正在尝试在我的iOS应用中进行智能搜索,以便当用户在UISearchBar中键入字符时,结果会自动在搜索栏下方的tableview中更新。出于某种原因,当我在搜索栏中键入一个字符时,不会调用带有textDidChange的searchBar函数。在输入2个字符后调用它。所以我的搜索结果总是落后于实际输入搜索栏的一步。而且似乎每次都会调用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;
}
答案 0 :(得分:1)
您需要实现UISearchResultsUpdating协议来实现此目的。它使用了一个UISearchController(在iOS 8中引入),它必须以编程方式而不是通过故事板添加,但不要担心,它非常简单。
这应该为你完成工作
干杯, 罗素
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
}
}
}