Smart-search for Parse Usernames in Swift not working
You will want to implement the UISearchResultsUpdating protocol to achieve this. It uses a UISearchController (introduced in iOS 8) which has to be added programmatically instead of through the storyboard, but don't worry, it's pretty straight-forward.
This should get the job done for you
Cheers,
Russell
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
}
}
}
Swift - Problems following & unfollowing users when searched via UISearchController [Parse]
You need to check if the UISearchController
is active inside of didSelectRowAtIndexPath
. Right now you are only selecting from the users
array instead of from the searchResults
array.
I also highly recommend refactoring your code away from using objectIds and use pointers. It is much easier to query against and work with pointers rather than directly accessing their objectIds.
Here's a link to another question that I've previously answered where I give a complete example of using a UISearchController
to search by usernames in Parse.. Hope this helps!
How to allow users to search based on two criteria
Try to edit your code like this:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
{
if searchText.isEmpty || searchText == " " {
inSearchMode = false
} else {
inSearchMode = true
filteredUsers = users.filter({ (user) -> Bool in
return (user.name?.contains(searchText) ?? true) || (user.occupation?.contains(searchText) ?? true)
})
}
tableView.reloadData()
}
Search bar not calling textDidChange for some reason
I got it working. Even though I specified searchBar.delegate = self
in viewDidLoad
, it did not work until I specified the searchBar
delegate in the storyboard interface.
Related Topics
Get Pixel Data as Array from Uiimage/Cgimage in Swift
Synchronous Url Request on Swift 2
Does This App Use the Advertising Identifier (IDFA)? - Admob 6.8.0
Xcode - There Are No Dsyms Available for Download
Uitapgesturerecognizer Tap on Self.View But Ignore Subviews
Prevent Dismissal of Modal View Controller in Swiftui
iOS Touch Event Notifications (Private API)
Error: Ld: Library Not Found for -Lpods with Cocoapods
Xcode 7.3.1 with iOS 10 Support
Convert an iOS Objective C Object to a JSON String
How to Use Core Location/Gps Without Any Internet Connection/Disabled Cellular Network
Xcode Simulator: How to Remove Older Unneeded Devices
How to Make View the Size of Another View in Swiftui
Custom Font Sizing in Xcode 6 Size Classes Not Working Properly with Custom Fonts
Distancefromlocation - Calculate Distance Between Two Points
Programmatically Switching Between Tabs Within Swift
Checking for Multiple Asynchronous Responses from Alamofire and Swift