Kyle Papili Kyle Papili - 4 years ago 162
Swift Question

Swift 3 Login Function

I am trying to write a login function in swift that sends and HTTP POST request to a webpage and then receives a JSON object in response. That part I got working perfectly; although, I am a bit confused with my code. Parts of it I got from online tutorials and I do not completely understand it. What I want to do is trigger a segue to another view when the login was successful. Also, when the login failed, I want to display a UILabel that says "Username and password don't match". Can someone help explain the code I have written and let me know how I can better implement it? Thank you.

ViewController:

class ViewController: UIViewController {
@IBOutlet var _username: UITextField!
@IBOutlet var _password: UITextField!
@IBOutlet var _button: UIButton!
@IBOutlet var errorText: UILabel!

@IBAction func loginButtonPress(_ sender: Any) {
let username = _username.text
let password = _password.text

if(username == "" || password == "") {
return
}

DoLogin(username: username!, password: password!)
}


DoLogin Function:

func DoLogin(username: String, password: String) {
let myUrl = URL(string: "http://MYURL.com");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"// Compose a query string
let postString = "username=\(username)&password=\(password)";
request.httpBody = postString.data(using: String.Encoding.utf8);

let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in

if error != nil
{
print("error=\(error)")
return
}

// Print out response object
print("response = \(response)")

//Convert response sent from a server side script to a NSDictionary object:
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
// Access value of username, name, and email by its key
let usernameValue = parseJSON["username"] as? String
let nameValue = parseJSON["name"] as? String
let emailValue = parseJSON["email"] as? String
print("usernameValue: \(usernameValue)")
print("nameValue: \(nameValue)")
print("emailValue: \(emailValue)")
if(usernameValue != nil && nameValue != nil && emailValue != nil) {
//The Login WAS SUCCESSFUL
//This is where I want to perform a segue to another view (like this)
//performSegue(withIdentifier: "loginToMain", sender: self) //This does not work
//Error above is (implicit use of 'self' in closuer; use 'self.' to make capture semantics explicit
}
} else {
//Username and Password do not match
print("Username and password do not match. Please Try again");
//This is what I want to do
self.errorText.isHidden = false
//But nothing happens to the errorText UILabel

}
} catch {
print(error)
}
}
task.resume()
}

Answer Source

Instead of performSegue put self.performSegue

And add a DispatchQueue wrapper to both of these

DispatchQueue.main.async
{
  self.performSegue(withIdentifier: "loginToMain", sender: self)
} 

..

 DispatchQueue.main.async {
     self.errorText.isHidden = false
}

When you are calling URLSession the code in its completion handler is running in a background thread, but GUI must be updated in the main thread. Adding DispatchQueue.main.async updates these in the main thread.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download