2

I want to retrieve the user score from Parse and assign it to a variable. This function returns 0 before the query finishes. I have found a similar answer at Retrieve object from parse.com and wait with return until data is retrieved. However, I expect the function have a return value and what argument should I use for the completionhandler when calling this function. Any help would be appreciated, thanks!

Here is my code

func loadCurrentUserData() -> Int {
        let query = PFQuery(className: "userScore")
        let userId = PFUser.currentUser()!
        var currentUserScore: Int = 0

        query.whereKey("user", equalTo: userId)
        query.findObjectsInBackgroundWithBlock {
        (objects: [PFObject]?, error: NSError?) -> Void in
        if error == nil {
            let scoreReceived = objects![0]["score"] as! Int
            currentUserScore = scoreReceived
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
            self.userScore.text = "\(scoreReceived)"
            })
        } else {
            print("Error: \(error!) \(error!.userInfo)")
            }
        }
        return currentUserScore
    }
1
  • I tried to add a semaphore. let semaphore = dispatch_semaphore_create(0) and dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER). But it still does't work. Commented Jan 18, 2016 at 18:21

1 Answer 1

4

The way you have set this function will not work as the query method is asynchronous. This can be fixed in two ways:

1) Use the PFQuery synchronous category: http://parse.com/docs/ios/api/Categories/PFQuery(Synchronous).html

The only disadvantage to this approach is that the method will become blocking so make sure to call it from a background thread.

2) Restructure the function to use a completion block instead of a return value..i.e:

    func loadCurrentUserData(completion: (score: Int!, error: NSError?) ->()) {
            let query = PFQuery(className: "userScore")
            let userId = PFUser.currentUser()!
            var currentUserScore: Int = 0

            query.whereKey("user", equalTo: userId)
            query.findObjectsInBackgroundWithBlock {
            (objects: [PFObject]?, error: NSError?) -> Void in
            if error == nil {
                let scoreReceived = objects![0]["score"] as! Int
                currentUserScore = scoreReceived
                dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.userScore.text = "\(scoreReceived)"
                })
                completion(score: currentUserScore, error: nil);
            } else {
                print("Error: \(error!) \(error!.userInfo)")
                }
                completion(score: currentUserScore, error: error);

            }
        }
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks John, but how to call this function later. And what if I want to pass the currentUserScore later to other functions?
Looks OK now! I'll remove my comments shortly after and also up vote. Thanks for considering the improvement.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.