matt
matt

Reputation: 99

Swift Wait for Callback to finish before method return

I'm using Siesta REST API client for swift. I'm logging into an external API (successfully) and get the result from the siesta request object. The request has two callbacks - onSuccess and onFailure.

If the login was successful I set a token in the keychain and then return the result to the view controller - which segues to a new view controller if successful.

However, as I'm assuming the callback is used asynchronously, my function is not returning the correct result.

 @IBAction func normalLoginButton(_ sender: UIButton) {

    //do normal login
    let standardLogin = StandardLogin()
    let credentials = ["email" : "[email protected]", "password": "password" ]
    let loginResult = standardLogin.login(params: credentials)
    print(loginResult)
    if loginResult {
        performSegue(withIdentifier: "showSuccessfulLoginView", sender: self)
    }

 }

 func login(params : Dictionary<String,String>) -> Bool{
    var loginSuccess = false
    let loginRequest = wrApi.makePostRequest(route: "login", params:params)

    loginRequest
        .onSuccess { data in
            print("succes")
            self.setJwtToken(jsonData: data.content)
            loginSuccess = true
        }
        .onFailure { error in print("an error occured")
    }


    return loginSuccess

}

My question is basically how do I wait for the callback to finish before returning my loginSuccess Boolean?

I'm pretty new to swift, so any help would be appreciated.

Upvotes: 1

Views: 6357

Answers (2)

Russell
Russell

Reputation: 5554

As @Nguyen points out, you can't return an immediate value from an async function. Given that all you're doing with the return value is performing your segue - just move that call into the completion handler

@IBAction func normalLoginButton(_ sender: UIButton) {
    //do normal login
    let standardLogin = StandardLogin()
    let credentials = ["email" : "[email protected]", "password": "password" ]
    standardLogin.login(params: credentials)
}


func login(params : Dictionary<String,String>){
    let loginRequest = wrApi.makePostRequest(route: "login", params:params)

    loginRequest
        .onSuccess { data in
            print("success")
            self.setJwtToken(jsonData: data.content)
            performSegue(withIdentifier: "showSuccessfulLoginView", sender: self)
    }
        .onFailure { error in print("an error occured")
    }
}

Upvotes: 1

Nguyen Hoan
Nguyen Hoan

Reputation: 1693

login is acsync function, so you can't use return Try closure:

   func login(params : Dictionary<String,String>, handleFinish:((isOK:Bool,param: Type?)->())){
       var loginSuccess = false
    let loginRequest = wrApi.makePostRequest(route: "login", params:params)

    loginRequest
        .onSuccess { data in
            print("succes")
            self.setJwtToken(jsonData: data.content)
            loginSuccess = true
            handleFinish(isOK: true, param :data.content )
        }
        .onFailure { error in 
                       print("an error occured")
                        handleFinish(isOK: false, param :nil )
    }

   }

and call it:

login(param) { (isOK, param) in
  if isOK{
   print("login success: \(param)")
 }

}

Upvotes: 4

Related Questions