Search code examples
iosswiftparse-platformpfuser

PFUser Query doesn't change variable at first run


I have a Textfield where a user can type in another users username, to add him as a friend. I'm using a PFQuery to query all the users and then I check if the username that is typed in the Textfield exists. If it exists, a button (I know I accidentally called it label in my text) appears and if the User presses the Button the other user should be added. I have a problem with the query, when I search for a user ( I know that this user exists) it doesn't print the username at the first run, only when I run it again. Seems like it changes the value only at the second time.

import UIKit
import Parse
import Bolts

var userToAdd = [String]()

class AddFriendViewController: UIViewController {

@IBOutlet var addFriendLabel: UIButton!
@IBOutlet var searchUserTF: UITextField!
override func viewDidLoad() {
    super.viewDidLoad()
    addFriendLabel.setTitle("", forState: .Normal)
    // Do any additional setup after loading the view.
}

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

func checkForUser() {

    if searchUserTF.text != "" {

        var username = searchUserTF.text            
        var query = PFUser.query()
        query?.findObjectsInBackgroundWithBlock({ (objects:[PFObject]?, error:NSError?) -> Void in

            for object in objects!{
            let recievedUser = (object as PFObject)["username"] as! String

                if recievedUser == username{
                    userToAdd.removeAll()
                    userToAdd.append(username!)

                    self.addFriendLabel.setTitle("Share myEvents with \(userToAdd[0])", forState: .Normal)
                }              
            } 
        })

    }  
}

@IBAction func searchButtonPressed(sender: AnyObject) {

    checkForUser()
    print(userToAdd)
    if addFriendLabel.hidden == true{

        let alertController = UIAlertController(title: "Username not found!", message: "A user with this username does not exist, please check the spelling or your internet connection", preferredStyle: .Alert)
        let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
        alertController.addAction(action)
        self.presentViewController(alertController, animated: true, completion: nil)

    } 
}

/*
// 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.
}
*/

}

print(userToAdd) only shows me ["Test"] when I click the button again, the first time I click it, it shows me []. I know I could also save it as a String and not as an Array, I was just playing around, because with a String I had the exact same problem.

I hope someone understands what I mean :D and knows a solution for my problem.


Solution

  • As the name of the function findObjectsInBackgroundWithBlock implies, the query operation completes in the background, so attempting to access userToAdd immediately after calling checkForUser() will give you nil because it hasn't been set as the query hasn't completed. The second time you press the button you are accessing the result of the first query which has now completed.

    You can use the completion closure (which is called a block in Objective-C, hence the WithBlock part of the function name to handle the result and display the error if required.

    You can also make your query much more efficient by using a whereKey to only retrieve the user you are after;

    import UIKit
    import Parse
    import Bolts
    
    var userToAdd=""
    
    class AddFriendViewController: UIViewController {
    
    @IBOutlet var addFriendLabel: UIButton!
    @IBOutlet var searchUserTF: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        addFriendLabel.setTitle("", forState: .Normal)
        // Do any additional setup after loading the view.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    @IBAction func searchButtonPressed(sender: AnyObject) {
    
        if searchUserTF.text != "" {
           let username=searchUserTF.text
            var query = PFUser.query()
            query.whereKey("username", equalTo:username)
            query?.findObjectsInBackgroundWithBlock({ (objects:[PFObject]?, error:NSError?) -> Void in
    
                if (error != nil) {
                   print(error)
                } else {
                   if objects!.count >0 {
                       self.addFriendLabel.setTitle("Share myEvents with \(username)", forState: .Normal)
                       self.userToAdd=username
                   } else {
                       self.userToAdd=""
                       let alertController = UIAlertController(title: "Username not found!", message: "A user with this username does not exist, please check the spelling or your internet connection", preferredStyle: .Alert)
                       let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
                       alertController.addAction(action)
                       self.presentViewController(alertController, animated: true, completion: nil)
                 }
             })
        }
    }