Completion handler not working as expected in Swif

2019-09-21 00:07发布

问题:

I have these two functions below, using a completion handler. The questions is highlighted in comments of the 2nd function... why is the result part getting executed even before the asynchronous call in function checforViolationStatus() been completed.

func checkViolationStatus(usr: PFUser, completion: (result: Int32) -> Void) {
    var violations: Int32 = 0
    var query = PFQuery(className: PF_BLOCKEDUSERS_CLASS_NAME)
    query.whereKey(PF_BLOCKEDUSERS_USER, equalTo: usr)


    query.countObjectsInBackgroundWithBlock {
        (count: Int32, error: NSError?) -> Void in
        if error == nil {
            print("Result = \(count)")

            //The result here returned is 4, I can see it but always ZERO(0) gets printed in the main function. Unable to understand why.
            violations = count
        }
    }

    completion(result: violations)

}


    func goToMainMenu() {

    if PFUser.currentUser() != nil {

        self.mCould.checkViolationStatus(PFUser.currentUser()!) {
            (result: Int32) in

            //QUESTION: result is getting returned as ZERO even before the actual asynchronous call in the checkforViolation function has been completed - why????

            if result < 4 {
                //Go to Main Menu Screen
                print("result<=4 so calling segue")
                self.performSegueWithIdentifier("segueLoginVCToMainVC", sender: nil)
            } else {
                print("result >=4, so should not be doing anything")
            }

            print("Number of Violations Received Back: \(result)")

        }
    }


}

回答1:

Try change your function to this,you should call completion in the countObjectsInBackgroundWithBlock,this method is async.

Or this function return before countObjectsInBackgroundWithBlock is finished

func checkViolationStatus(usr: PFUser, completion: (result: Int32) -> Void) {
var violations: Int32 = 0
var query = PFQuery(className: PF_BLOCKEDUSERS_CLASS_NAME)
query.whereKey(PF_BLOCKEDUSERS_USER, equalTo: usr)


query.countObjectsInBackgroundWithBlock {
    (count: Int32, error: NSError?) -> Void in
    if error == nil {
        print("Result = \(count)")

        //The result here returned is 4, I can see it but always ZERO(0) gets printed in the main function. Unable to understand why.
        violations = count
        completion(result: violations)

    }
}
}