Pix And Codes Pix And Codes - 3 months ago 11
Swift Question

completion handler with POST request

I have simple login method which returns bool, depends on success of user login. I have problem with order of the responses and execution of the code. I've read about completion handlers, for which I think are solution to my problems but I'm not sure. Here is my method:

//perform user login in, setting nsuserdefaults and returning the bool result
func login(username: String, password:String) -> (Bool) {

var success:Bool = false

//sending inputs to server and receiving info from server
let postRequest = postDataToURL()
postRequest.link = "http://pnc.hr/rfid/login.php"
postRequest.postVariables = "username=" + username + "&password=" + pass

word

postRequest.forData("POST") { jsonString in
// getting the result from the asinhronys task
let result = convertStringToDictionary(jsonString as String)
if let loggedIn = result?["loggedIn"] as? Bool where loggedIn == true {

let userType = result?["userType"] as? String
let token = result?["token"] as? String

//if user is logged - setting parameters in Key Chains and redirecting them to the menu view
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(loggedIn, forKey: "loggedIn")
defaults.setObject(username, forKey: "username")
defaults.setObject(userType, forKey: "userType")
defaults.setObject(token, forKey: "token")

success = true
}
else {
success = false
}
print ("class - " + String(jsonString))
print ("classIN - " + String(success))
}

print ("classOUT - " + String(success))
return success
}


I would like to make return of success variable inside if statement which checks variable loggedIn is equal to true. But in that case I get error.

Then I have made this method. The problem is that method returns the variable success quicker than the POST request has been done. So it will be false in every case. I have printed variables to see the order of the code execution and method first prints the "classOUT", returns the variable, and then sets up variable value and print "classIN".

How can I wait until the code which logs user gets executed so I can get the right value of the variable success?

Answer

Perform user login in, setting nsuserdefaults and returning the bool result

completionBlock: is that block which will get executed when you call it like any block but you get to choose when and what all to pass through that block.

    func login(username: String, password:String,completionBlock : ((success : Bool)->Void)){

        //sending inputs to server and receiving info from server
        let postRequest = postDataToURL()
        postRequest.link = "http://pnc.hr/rfid/login.php"
        postRequest.postVariables = "username=" + username + "&password=" + password

    postRequest.forData("POST") { jsonString in
        // getting the result from the asinhronys task
        let result = convertStringToDictionary(jsonString as String)
        if let loggedIn = result?["loggedIn"] as? Bool where loggedIn == true {

            let userType = result?["userType"] as? String
            let token = result?["token"] as? String

            //if user is logged - setting parameters in Key Chains and redirecting them to the menu view
            let defaults = NSUserDefaults.standardUserDefaults()
            defaults.setObject(loggedIn, forKey: "loggedIn")
            defaults.setObject(username, forKey: "username")
            defaults.setObject(userType, forKey: "userType")
            defaults.setObject(token, forKey: "token")

            completionBlock(success:true)
        }
        else {
            completionBlock(success:false)
        }
    }
}

when you call it would look something like this:-

    login(username: String, password:String,completionBlock : { (success) in
     print(success)
  })