trying to implement the uisearchcontroller but its not giving any search result - ios

import UIKit
class MasterTableViewController: UITableViewController, PFLogInViewControllerDelegate, PFSignUpViewControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating {
//approches for uisearchbar
var searchNotes: [PFObject] = [PFObject]()
var notesSearchController = UISearchController()
var searchActive: Bool = false
// creating array for holding ojects
var noteObjects: NSMutableArray! = NSMutableArray()
var v = 0
override func viewDidLoad() {
super.viewDidLoad()
self.notesSearchController = UISearchController(searchResultsController: nil)
self.notesSearchController.dimsBackgroundDuringPresentation = true
self.notesSearchController.searchResultsUpdater = self
// Configure the search controller's search bar
self.notesSearchController.searchBar.placeholder = "Search for a user"
self.notesSearchController.searchBar.sizeToFit()
self.notesSearchController.searchBar.delegate = self
self.definesPresentationContext = true
// Set the search controller to the header of the table
self.tableView.tableHeaderView = self.notesSearchController.searchBar
print("check")
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if v == 0 {
self.fetchAllObjectsFromLocalDataStore()
//self.fetchAllObjects()
}
}
// fetching data from local datastore and from parse
func fetchAllObjectsFromLocalDataStore(){
let query: PFQuery = PFQuery(className: "Sinhgad")
query.orderByDescending("createdAt")
query.fromLocalDatastore()
query.findObjectsInBackgroundWithBlock { ( objects, error) -> Void in
if (error == nil) {
let temp: NSArray = objects as NSArray!
self.noteObjects = temp.mutableCopy() as! NSMutableArray
self.tableView.reloadData()
}else {
print(error!.userInfo)
}
}
}
func fetchAllObjects(){
let query: PFQuery = PFQuery(className: "Sinhgad")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if (error == nil) {
PFObject.pinAllInBackground(objects, block: nil )
self.fetchAllObjectsFromLocalDataStore()
// self.tableView.reloadData()
} else {
print(error?.userInfo)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if (self.notesSearchController.active) {
return self.searchNotes.count
} else {
return self.noteObjects.count
}}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MasterTableViewCell
if (self.notesSearchController.active && self.searchNotes.count > indexPath.row) {
// bind data to the search results cell
let object : PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
cell.MasterTitleLabel?.text = object["Title"] as? String
cell.MasterTextLabel.text = object["Fstory"] as? String
cell.MasterTimeLabel.text = object["Time"] as? String
cell.MasterLocationLabel.text = object["Location"] as? String
return cell
} else {
let object : PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
cell.MasterTitleLabel?.text = object["Title"] as? String
cell.MasterTextLabel.text = object["Fstory"] as? String
cell.MasterTimeLabel.text = object["Time"] as? String
cell.MasterLocationLabel.text = object["Location"] as? String
return cell
}}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if (self.notesSearchController.active && self.searchNotes.count > 0) {
// Segue or whatever you want
self.performSegueWithIdentifier("openStory", sender: self)
} else {
self.performSegueWithIdentifier("openStory", sender: self)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let upcoming: AddNoteTableViewController = segue.destinationViewController as! AddNoteTableViewController
if (segue.identifier == "openStory"){
let indexPath = self.tableView.indexPathForSelectedRow!
let object: PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
upcoming.object = object
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
#IBAction func btnReload(sender: AnyObject) {
fetchAllObjects()
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete ){
let object : PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
// the below for deleting the selected cell's object from server's database
// object.deleteInBackground()
//the below for deleting the selected cell's object from localstorage
object.unpinInBackground()
self.noteObjects.removeObjectAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
// MARK: - Parse Backend methods
func loadSearchUsers(searchString: String) {
let query: PFQuery = PFQuery(className: "Sinhgad")
query.orderByDescending("createdAt")
// Filter by search string
query.whereKey("Notes", containsString: searchString)
self.searchActive = true
query.findObjectsInBackgroundWithBlock {(objects, error) -> Void in
if (error == nil) {
self.searchNotes.removeAll(keepCapacity: false)
self.searchNotes += objects as [PFObject]!
self.tableView.reloadData()
} else {
// Log details of the failure
print("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)
}
}
}
The above code is for retrieving stored objects from parse's server and from local storage and show them in table view.
Everything is working fine but I am trying to implement searchbar for adding searching function into my app. The problem is that when am running the app its showing the searchbar but when interacting with search bar its moving to upside and disappearing and when am typing anything.
I am not getting any search result and in NSLog am getting this :
2015-12-03 16:43:48.769 Notes[1015:56944] Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior (<UISearchController: 0x7ff2d48165a0>)
I know am missing something and its not the right way to achieve that function.
If somebody knows how to do it correctly or what am missing than please let me know , thanks and sorry if the way am asking question is not proper !
i just figured out that my 'searchNotes' var of Pfobject have nothing i mean its empty ! for that i tried
cell.MasterTitleLabel?.text = searchNotes["Title"] as! String
but its giving error
cannot subscript a value of type '[PFObject]' with an index of type 'string'
i know its because i declared searchNotes as
searchNotes [PFObject] = [PFObject]()
i should do it something like
searchNotes PFObject = PFObject()
but when am doing this its giving so many errors please help if somebody's know how to fix this

Maybe you shouldn't user PFObject directly.
Can you use another class instead of PFObject
private class object {
var mTitle : String!
var mStory : String!
var mTime : String!
var mLocation : String!
}
And use your code here
let obj : object = object()
obj.mTitle = PFObject["title"];
...etc

Related

tableview error while searching

Hi I have two arrays and only one array is updating with search bar.. I keep the TitleArray to show in tableView title and detailsArray to show in tableView subtitle.. once I start searching only title following my typing but subtitle nothing change.
#IBOutlet weak var AirportsTableView: UITableView!
var TitleArray = [String]()
var DetailsArray = [String]()
var NumberOfRows = 0
var filteredNamesArray = [String]()
var filteredDetailsArray = [String]()
var resultSearchController = UISearchController!()
**override func viewDidLoad() {
super.viewDidLoad()**
// Do any additional setup after loading the view.
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController.searchResultsUpdater = self
self.resultSearchController.dimsBackgroundDuringPresentation = false
self.resultSearchController.searchBar.sizeToFit()
self.resultSearchController.loadViewIfNeeded()
self.AirportsTableView.tableHeaderView = self.resultSearchController.searchBar
self.AirportsTableView.reloadData()
parseJSON()
}
func parseJSON() {
if let path = NSBundle.mainBundle().pathForResource("airports", ofType: "json") {
do {
let data = try NSData(contentsOfURL: NSURL(fileURLWithPath: path), options: NSDataReadingOptions.DataReadingMappedIfSafe)
let jsonObj = JSON(data: data)
if jsonObj != JSON.null {
// print("jsonData:\(jsonObj)")
NumberOfRows = jsonObj.count
for i in 0...NumberOfRows {
let City = jsonObj[i]["city"].string as String!
let Country = jsonObj[i]["country"].string as String!
let Iata = jsonObj[i]["iata"].string as String!
let Name = jsonObj[i]["name"].string as String!
self.TitleArray.append("\(City) - \(Country) - \(Iata)")
self.DetailsArray.append("\(Name)")
}
} else {
print("could not get json from file, make sure that file contains valid json.")
}
} catch let error as NSError {
print(error.localizedDescription)
}
} else {
print("Invalid filename/path.")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
// MARK: - Table view data source
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if self.resultSearchController.active
{
return self.filteredNamesArray.count
} else
{
return self.TitleArray.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell?
if self.resultSearchController.active
{
cell!.textLabel?.text = self.filteredNamesArray[indexPath.row]
} else
{
cell!.textLabel?.text = self.TitleArray[indexPath.row]
cell!.detailTextLabel?.text = self.DetailsArray[indexPath.row]
}
return cell!
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
self.filteredNamesArray.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text!)
let array = (self.TitleArray as NSArray).filteredArrayUsingPredicate(searchPredicate)
self.filteredNamesArray = array as! [String]
self.AirportsTableView.reloadData()
}
// MARK: - Segues
/*
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "AirportDetails" {
if let indexPath = self.AirportsTableView.indexPathForSelectedRow {
let airportDetail : Airports = TitleArray[indexPath.row]
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! AllWaysFlightsViewController
controller.airportDetail = airportDetail
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
*/
Instead of using two separate arrays use only one array and populate it with object containing both variables you are using to populate the tableView.
class Address {
var city: String
var detail: String
init(city: String, detail:String) {
self.city = city
self.detail = detail
}
}
Parse your json like this:
for i in 0...NumberOfRows {
let City = jsonObj[i]["city"].string as String!
let Country = jsonObj[i]["country"].string as String!
let Iata = jsonObj[i]["iata"].string as String!
let Name = jsonObj[i]["name"].string as String!
let city = "\(City) - \(Country) - \(Iata)"
let address = Address(city: city, detail: Name)
self.TitleArray.append(address)
self.filteredNamesArray.append(address)
}
Filter your title array containing addresses. Your titlearray and filtered array both contains same data for the first time you can refer to the json parsing for this. Here you can use one for filtering and when search bar is empty it user cancel his search you can re-populate your array from the other one.
func updateSearchResultsForSearchController(searchController: UISearchController) {
self.filteredNamesArray.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF.city CONTAINS[c] %#", searchController.searchBar.text!)
let array = (self.TitleArray as NSArray).filteredArrayUsingPredicate(searchPredicate)
self.filteredNamesArray = array as! [Address]
self.AirportsTableView.reloadData()
}
your tableView logic will be changed accordingly
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.filteredNamesArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell?
let address = self.filteredNamesArray[indexPath.row]
cell!.textLabel?.text = address?.city
cell!.detailTextLabel?.text = address?.detail
return cell!
}
You need to change the way you approach filtering the data so that rather than just apply a predicate you explicitly iterate and check the predicate, if you find a match then you take that item and the corresponding description into your filtered arrays.
Something like:
func updateSearchResultsForSearchController(searchController: UISearchController) {
self.filteredNamesArray.removeAll(keepCapacity: false)
self.filteredDetailsArray.removeAll(keepCapacity: false)
let searchString = searchController.searchBar.text!
var index = 0
for title in self.TitleArray
if title.rangeOfString(searchString).location != NSNotFound {
self.filteredNamesArray.append(title)
self.filteredDetailsArray.append(self.DetailsArray[index])
}
index += 1
}
self.AirportsTableView.reloadData()
}

Swift - Search always executing before full text

I have a class that handles the user looking for another user via the username. The looking part is done through SearchBar control. Backend is Firebase.
Here is the full code I have:
class AddFriendByUsernameTableViewController: UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate {
/**************************Global Variables************************/
var friendObject = FriendClass()
var friendsArray = [FriendClass]()
var friendsUsernames = [String]()
var isFirstLoading: Bool = true
var utiltiies = Utilities()
var searchActive : Bool = false
var usernames:[String]!
/**************************UI Components************************/
#IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
self.searchBar.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func search(searchText: String? = nil){
/****************************Get Username by Auth Data****************************/
if(searchText != nil)
{
self.getAllUsersForSearchFilter({(result) -> Void in
if(result.domain == "")
{
let containsResult = self.usernames.contains(searchText!)
if(containsResult == true)
{
/*Query All information for found username*/
let reference = Firebase(url:"https://something.firebaseio.com/users/")
/****************************Get Username by Auth Data****************************/
reference.queryEqualToValue(searchText!).observeEventType(.Value, withBlock: { (snapshot: FDataSnapshot!) -> Void in
for userInstance in snapshot.children.allObjects as! [FDataSnapshot]{
}
})
}else{
print("No matching username to search Text")
}
}
})
}
}
func getAllUsersForSearchFilter(completion: (result: NSError) -> Void)
{
let errorFound:NSError = NSError(domain: "", code: 0, userInfo: nil)
let reference = Firebase(url:"https://something.firebaseio.com/users/")
reference.observeEventType(.Value, withBlock: { (snapshot: FDataSnapshot!) -> Void in
if(snapshot != nil )
{
for userInstance in snapshot.children.allObjects as! [FDataSnapshot]{
//username = (userInstance.value["username"] as? String)!
//self.usernames.append(userInstance.value["username"] as! String)
}
completion(result: errorFound)
}else{
completion(result: errorFound)
}
})
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if(usernames != nil)
{
return usernames.count
}
return 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
//self.tempObjectHolder = self.data[indexPath.row]
//cell.textLabel!.text = self.tempObjectHolder["appUsername"] as? String
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPathT = tableView.indexPathForSelectedRow;
let currentCell = tableView.cellForRowAtIndexPath(indexPathT!)
/*Get username selected from the search results. */
self.friendObject.username = currentCell?.textLabel!.text
/*self.friendObject.name = self.tempObjectHolder["name"] as? String
self.friendObject.mobile = self.tempObjectHolder["mobile"] as? String
self.friendObject.telephone = self.tempObjectHolder["telephone"] as? String
self.friendObject.username = self.tempObjectHolder["appUsername"] as? String
self.friendObject.email = self.tempObjectHolder["email"] as? String
self.friendObject.workAddressString = self.tempObjectHolder["workAddress"] as! String
self.friendObject.homeAddressString = self.tempObjectHolder["homeAddress"] as! String*/
self.performSegueWithIdentifier("viewUserResultsSegue", sender: self)
}
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
searchActive = true;
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
search()
searchActive = false;
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
search(searchText)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "viewUserResultsSegue") {
// pass data to next view
//let destinationVC = segue.destinationViewController as! ViewResultUserProfileViewController
//destinationVC.friendObject = self.friendObject;
}
}
}
When I start typing in the the search bar, it executes and triggers an erro:
fatal error: unexpectedly found nil while unwrapping an Optional value
and this is happening because it took the firt character I entered and searched for it. I want it to search for full work (username) not first letters.
Thanks,
To do some action when the keyboard Enter is tapped, you can create an IBAction method in your view controller, such as:
#IBAction func enterDetected(sender: UITextField) {
print("Saw an 'Enter'")
}
Then connect the UITextField's "Primary Action Triggered" connection to the method in Interface Builder.

issue following / unfollowing users when searched for? Parse

Good Afternoon,
Today I am having some issues with parse.
I have created a UISearchController, loaded my users from parse so I can search for individual ones and I have added a following and unfollowing feature.
My Problem is when I search for a specific user and try to follow him: So I search for a specific user say "test" it shows up as it should, but when I click follow and then go back to parse to see if "I" have followed test I can a different result.
It says I have followed for example "tester" which was the first user created. Its seeming to follow the Cell and now the userId...
After that I manged to get the users in alphabetical order, but same problem here except it follows the first user in alphabetical order for example if I have a username that begins with an "A"!
I'm not sure how to fix this issue, so I'm hoping someone here does..I accept and appreciate all kind of tips and answers!
Heres my code:
class yahTableViewController: UITableViewController, UISearchResultsUpdating {
var users: [PFUser] = [PFUser]()
var followingList: [PFUser] = [PFUser]()
var searchResults: Bool = false
var resultSearchController = UISearchController()
var refresher: UIRefreshControl!
#IBOutlet var userTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController.searchResultsUpdater = self
self.resultSearchController.hidesNavigationBarDuringPresentation = false
self.navigationItem.titleView = resultSearchController.searchBar
self.resultSearchController.dimsBackgroundDuringPresentation = false
self.definesPresentationContext = true
self.resultSearchController.searchBar.sizeToFit()
self.resultSearchController.searchBar.barStyle = UIBarStyle.Black
self.resultSearchController.searchBar.tintColor = UIColor.whiteColor()
for subview in self.resultSearchController.searchBar.subviews
{for subsubView in subview.subviews
{if let textField = subsubView as? UITextField
{textField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Search", comment: ""), attributes: [NSForegroundColorAttributeName: UIColor.whiteColor()])
textField.textColor = UIColor.whiteColor()
}}}
tableView.tableFooterView = UIView()
self.tableView.separatorInset = UIEdgeInsets(top: 10, left: 15, bottom: 10, right: 15)
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "")
refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
self.tableView.addSubview(refresher)
}
//Function used to load the users on first view load or when the UI refresh is performed
private func loadUsers(searchString: String){
func refresh() {
let query = PFUser.query()
query!.whereKey("username", containsString: searchString )
self.searchResults = true
query!.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if (error == nil) {
self.users.removeAll(keepCapacity: false)
self.users += objects as! [PFUser]
self.tableView.reloadData()
} else {
// Log details of the failure
print("search query error: \(error) \(error!.userInfo)")
}
// Now get the following data for the current user
let query = PFQuery(className: "followers")
query.whereKey("follower", equalTo: PFUser.currentUser()!)
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if (error == nil) {
self.followingList.removeAll(keepCapacity: false)
self.followingList += objects as! [PFUser]
self.userTableView.reloadData()
} else
if error != nil {
print("Error getting following: \(error) \(error!.userInfo)")
}
})
}
self.searchResults = false
self.tableView.reloadData()
self.refresher.endRefreshing()
}}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
// Force search if user pushes button
let searchString: String = searchBar.text!.lowercaseString
if (searchString != "") {
loadUsers(searchString)
}
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBar.text = ""
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
let searchString: String = searchController.searchBar.text!.lowercaseString
if (searchString != "" && !self.searchResults) {
loadUsers(searchString)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.resultSearchController.active) {
return self.users.count
} else {
return self.users.count
// return whatever your normal data source is
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let Cell = tableView.dequeueReusableCellWithIdentifier("Cell")! as UITableViewCell
if (self.resultSearchController.active && self.users.count > indexPath.row) {
let userObject = users[indexPath.row]
Cell.textLabel?.text = userObject.username
for following in followingList {
if following["following"] as? String == PFUser.currentUser()! {
//Add checkbox to cell
Cell.accessoryType = UITableViewCellAccessoryType.Checkmark
break
}}
// 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) {
if let selectedUser = users[indexPath.row] as? PFUser {
// Now get the following/following data for the current user
let query = PFQuery(className: "Followers")
query.whereKey("follower", equalTo: (PFUser.currentUser()?.objectId)!)
query.whereKey("following", equalTo: (selectedUser.objectId)!)
query.getFirstObjectInBackgroundWithBlock({ (object, error) -> Void in
if error != nil && object == nil {
// Means the record doesn't exist
self.insertFollowingRecord(selectedUser, selectedIndexPath: indexPath)
} else {
// Means record is present, so we will delete it
if let followingObject = object {
followingObject.deleteInBackground()
let cell:UITableViewCell = self.userTableView.cellForRowAtIndexPath(indexPath)!
//Remove checkbox from cell
cell.accessoryType = UITableViewCellAccessoryType.None
}
}
})
}
}
private func insertFollowingRecord (selectedUser:PFUser, selectedIndexPath: NSIndexPath) -> Void {
// Now add the data for following in parse
let following:PFObject = PFObject(className: "Followers")
following["following"] = selectedUser.objectId
following["follower"] = PFUser.currentUser()?.objectId
following.saveInBackgroundWithBlock({ (success, error) -> Void in
if success {
let cell:UITableViewCell = self.userTableView.cellForRowAtIndexPath(selectedIndexPath)!
//Add checkbox to cell
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
} else if error != nil {
print("Error getting following: \(error) \(error!.userInfo)")
}
})
}
}
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
Courtesy of Russel.
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
}
}
}

Filter an Array of data for use in a UITableView

I'm trying to filter an array that I create based on objects (as Strings) that I queried. They show up great, now I just want to filter and remake the array so that I can filter out the information I need. I'm not sure why I'm getting "Result of call 'filter' Is unused" in Xcode. I looked around but I can't figure this one out.
import UIKit
class RegionStoreTableViewController: UITableViewController, UISearchBarDelegate {
var selectedRegionStore : String? = nil
var selectedRegionStoreIndex : Int? = nil
var dataArray = [String]()
var filteredArray = [String]()
var employeeType : String? = nil
var searchText = ""
#IBOutlet weak var regionStoreSearchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
let prefs = NSUserDefaults.standardUserDefaults()
if prefs.valueForKey("EmployeeType") != nil {
employeeType = prefs.valueForKey("EmployeeType") as! String
// Employee Type
// Retail
if employeeType == "Retail" {
self.navigationItem.title = "Store Selector"
let query = PFQuery(className: "Stores")
query.orderByAscending("rStoreNumber")
query.findObjectsInBackgroundWithBlock({ (store: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
for store in store! {
let theStore = store["storeName"] as! String
let storeNumber = store["rStoreNumber"] as! String
let storeString = storeNumber + " - " + theStore
print(theStore)
self.dataArray.append(storeString)
self.tableView.reloadData()
}
}
})
}
if employeeType == "Corporate" {
let query = PFQuery(className: "Regions")
query.orderByAscending("regionName")
query.findObjectsInBackgroundWithBlock { (region: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
for region in region! {
let theRegion = region["regionName"] as! String
print(theRegion)
self.dataArray.append(theRegion)
self.tableView.reloadData()
}
} else {
print(error)
}
}
}
}
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(dataArray.count)
return dataArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("RegionStoreCell", forIndexPath: indexPath)
if searchText.isEmpty {
cell.textLabel?.text = dataArray[indexPath.row]
}
if searchText != "" {
dataArray.filter() {nil != $0.containsString(searchText) }
}
if indexPath.row == selectedRegionStoreIndex {
cell.accessoryType = .Checkmark
} else {
cell.accessoryType = .None
}
return cell as UITableViewCell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
if let index = selectedRegionStoreIndex {
let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0))
cell?.accessoryType = .None
}
selectedRegionStoreIndex = indexPath.row
selectedRegionStore = dataArray[indexPath.row]
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell?.accessoryType = .Checkmark
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SaveSelectedRegionStore" {
let cell = sender as! UITableViewCell
let indexPath = tableView.indexPathForCell(cell)
selectedRegionStoreIndex = indexPath?.row
if let index = selectedRegionStoreIndex {
selectedRegionStore = dataArray[index]
}
}
}
// MARK: Search Bar
// delegate in story board
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
searchBar.showsCancelButton = true
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
searchBar.showsCancelButton = false
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
// add minimum length of search
searchText = searchBar.text!
self.tableView.reloadData()
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
// clear out search box
searchBar.text = nil
// clear out search variable
searchText = ""
// reload the table
self.tableView.reloadData()
// hide keyboard
searchBar.resignFirstResponder()
}
}
Any suggestions?
I think you need to store your filtered array into another array.
let filterArray = dataArray.filter() {nil != $0.containsString(searchText)

Table cells not in order using parse Swift

I'm using parse to make a simple notes app. When I save a note the cells appear in a random order in the table view. Can anyone help me figure out how to fix this so the cells are in order from when I saved a note. Thanks!
import UIKit
class MasterTableViewController: UITableViewController, PFLogInViewControllerDelegate, PFSignUpViewControllerDelegate {
var noteObjects: NSMutableArray! = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if (PFUser.currentUser() == nil) {
}else {
self.fetchAllObjectsFromLocalDatastore()
self.fetchAllObjects()
}
}
func fetchAllObjectsFromLocalDatastore() {
var query: PFQuery = PFQuery(className: "Note")
query.fromLocalDatastore()
query.whereKey("username", equalTo: PFUser.currentUser()!.username!)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if (error == nil) {
var temp: NSArray = objects!; NSArray.self
self.noteObjects = temp.mutableCopy() as! NSMutableArray
self.tableView.reloadData()
}else {
}
}
}
func fetchAllObjects() {
PFObject.unpinAllObjectsInBackgroundWithBlock(nil)
var query: PFQuery = PFQuery(className: "Note")
query.whereKey("username", equalTo: PFUser.currentUser()!.username!)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if (error == nil) {
PFObject.pinAllInBackground(objects, block: { (success, error) in
if error == nil {
self.fetchAllObjectsFromLocalDatastore()
}
})
}else {
println(error!.userInfo)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return self.noteObjects.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MasterTableViewCell
var object: PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
cell.masterTitleLabel?.text = object["title"] as? String
cell.masterTextLabel?.text = object["text"] as? String
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("editNote", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var upcoming: AddNoteTableViewController = segue.destinationViewController as! AddNoteTableViewController
if (segue.identifier == "editNote") {
let indexPath = self.tableView.indexPathForSelectedRow()!
var object: PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
upcoming.object = object
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
}
What you need is to set a sorting for your query.
You can sort it by the UpdatedAt date with the following line of code:
query.ascending("updatedAt");

Resources