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
}
}
}
Related
I am creating a view that shows a list of users. The current user is able to click on one of the cells, thus following or unfollowing the user in that cell. For some reason, checkmarks are showing up in cells that should not have the checkmark(meaning the current user is following someone that he really isn't). The images for the users are also incorrect. I imagine the reason for that is related to the checkmark error. What am I doin wrong? PLEASE HELP!
import UIKit
import Parse
class TableViewController: UITableViewController {
var refresher: UIRefreshControl!
var usernames = [""]
var userIds = [""]
var userPics = [String:PFFile]()
var isFollowing = ["":false]
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.hidesBackButton = true
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
self.tableView.addSubview(refresher)
refresh()
}
func refresh (){
let query = PFUser.query()
query?.findObjectsInBackgroundWithBlock({ (object, error) -> Void in
if let users = object {
self.usernames.removeAll(keepCapacity: true)
self.userIds.removeAll(keepCapacity: true)
self.isFollowing.removeAll(keepCapacity: true)
self.userPics.removeAll(keepCapacity: true)
for objects in users {
if let user = objects as? PFUser {
if user.objectId != PFUser.currentUser()?.objectId {
self.usernames.append(user.username!)
self.userIds.append(user.objectId!)
if let image = user["profileImage"] {
self.userPics[user.objectId!] = image as? PFFile
}
let query = PFQuery(className: "Followers")
query.whereKey("following", equalTo: user.objectId!)
query.whereKey("follower", equalTo: (PFUser.currentUser()!.objectId)!)
query.findObjectsInBackgroundWithBlock({ (object, error) -> Void in
if let object = object {
if object.count > 0 {
self.isFollowing[user.objectId!] = true
} else {
self.isFollowing[user.objectId!] = false
}
}
if self.isFollowing.count == self.usernames.count {
print(self.isFollowing)
print(self.userIds)
self.tableView.reloadData()
self.refresher.endRefreshing()
}
})
}
}
}
}
})
}
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
return usernames.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UsersTableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UsersTableViewCell
cell.userLabel.text = usernames[indexPath.row]
if isFollowing[userIds[indexPath.row]] == true {
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
}
cell.userImage.frame = CGRectMake(0, 0, 100, 100)
cell.userImage.clipsToBounds = true
cell.userImage.layer.cornerRadius = cell.userImage.frame.height/2
if userPics[userIds[indexPath.row]] != nil {
userPics[userIds[indexPath.row]]!.getDataInBackgroundWithBlock { (data, error) -> Void in
if let data = data {
cell.userImage.image = UIImage(data: data)
}
}
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell: UsersTableViewCell = tableView.cellForRowAtIndexPath(indexPath)! as! UsersTableViewCell
if isFollowing[userIds[indexPath.row]] == false {
isFollowing[userIds[indexPath.row]] = true
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
let following = PFObject(className: "Followers")
following["following"] = userIds[indexPath.row]
following["follower"] = PFUser.currentUser()?.objectId
following.saveInBackground()
} else {
isFollowing[userIds[indexPath.row]] = false
cell.accessoryType = UITableViewCellAccessoryType.None
let query = PFQuery(className: "Followers")
query.whereKey("following", equalTo: userIds[indexPath.row])
query.whereKey("follower", equalTo: (PFUser.currentUser()?.objectId)!)
query.findObjectsInBackgroundWithBlock({ (object, error) -> Void in
if let object = object {
for users in object {
users.deleteInBackground()
}
}
})
}
}
}
Like Michael said, you need to clear the checkmark, try with this code instead of your if
cell.accessoryType = isFollowing[userIds[indexPath.row]] ? UITableViewCellAccessoryType.Checkmark : UITableViewCellAccessoryType.None
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.
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
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)
i trie to find parse users via UISearchBar and display results in a table view.
When i heat search, nothing happened...
My idea was to use the searchText.text as a query to PFUser.
Should i try to use searchBar with search display controller instead ?
Any idea ?
import UIKit
class AllFriendsTableViewController: UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate {
#IBOutlet var SearchDisplay: UISearchDisplayController!
var userList:NSMutableArray = NSMutableArray()
func searchBarShouldBeginEditing(searchBar: UISearchBar!) -> Bool {
return true
}
func searchBarShouldEndEditing(searchBar: UISearchBar!) -> Bool {
return true
}
func searchBar(searchBar: UISearchBar!, textDidChange searchText: String!) {
loadUser()
}
#IBOutlet var searchText: UISearchBar!
func loadUser () {
userList.removeAllObjects()
var findUser:PFQuery = PFUser.query()
findUser.whereKey("username", equalTo: searchText.text)
findUser.findObjectsInBackgroundWithBlock { (objects:[AnyObject]!, error:NSError!) -> Void in
if !(error != nil) {
// The find succeeded.
println("succesfull load Users")
// Do something with the found objects
for object in objects {
self.userList.addObject(object)
println("users added to userlist")
}
self.tableView.reloadData()
} else {
// Log details of the failure
println("error loadind user ")
println("error")
}
}
}
override func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
return 1
}
override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
if tableView == searchDisplayController.searchResultsTableView {
return userList.count
}
else {
return 0
}
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell: AllFirendsTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)as AllFirendsTableViewCell
let users:PFObject = self.userList.objectAtIndex(indexPath!.row) as PFObject
var findUserName:PFQuery = PFUser.query()
findUserName.whereKey("username", containsString: searchText.text)
findUserName.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!) -> Void in
if !(error != nil) {
if let user:PFUser = users as? PFUser {
cell.userNameTextField.text = user.username
println("user exist")
// define avatar poster
if let avatarImage:PFFile = user["profileImage"] as? PFFile {
avatarImage.getDataInBackgroundWithBlock{(imageData:NSData!, error:NSError!)-> Void in
if !(error != nil) {
let image:UIImage = UIImage(data: imageData)
cell.avatarImage.image = image as UIImage
cell.avatarImage.layer.cornerRadius = 24
cell.avatarImage.clipsToBounds = true
}
}
}
else {
cell.avatarImage.image = UIImage(named: "Avatar-1")
cell.avatarImage.layer.cornerRadius = 24
cell.avatarImage.clipsToBounds = true
}
}
}
}
return cell
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
navigationController.navigationBar.hidden = false
loadUser()
}
override func viewDidAppear(animated: Bool) {
}
override func viewDidLoad() {
// Do any additional setup after loading the view, typically from a nib.
}
}
I suspect this might be due to you attempting to reload the tableview from the background thread that your network request occurs on. UI updates should happen from the main thread.
In your loadUser() function try doing your tableview reload from the main thread, as follows:
NSOperationQueue.mainQueue().addOperationWithBlock({
self.tableView.reloadData()
})
That may fix your issue.