cruise_lab
cruise_lab

Reputation: 659

If user does not exist should display an error Message with UIAlert

I am currently working on a IOS App using Swift 3. I am working on the login system. Verification of logging in works fine. The logic is that, if login succeeds, it goes to the next Screen. However, if user does not exist, it should display an error message with UIAlert. But when I try to display the UIAlert, i get an error that says "Assertion failure in -[UIKeyboardTaskQueue waitUntilAllTasksAreFinished]"

//Getting data from database
    func getData() -> Void {

        let url: String = "http://localhost/fridge_app/login.php" //this will be changed to the path where service.php lives

        //created NSURL
        let requestURL = NSURL(string: url)

        //creating NSMutableURLRequest
        var request = URLRequest(url: requestURL! as URL)

        //setting the method to post
        request.httpMethod = "POST"


        //Getting values from textfield
        let usernameVal = username.text
        let passwordVal = password.text

        //creating the post parameter by concatenating the keys and values from text field
        let postString = "username=\(usernameVal!)&password=\(passwordVal!)";
        print(postString)
        request.httpBody = postString.data(using: String.Encoding.utf8)

        //creating a task to send the post request
        let task = URLSession.shared.dataTask(with: request as URLRequest){
            data, response, error in

            //exiting if there is some error
            if error != nil{
                print("error is \(error)")
                return;
            }

            // Print out response string
            var responseString: NSString?;
            responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
            if(responseString == "invalid"){
                self.isValid = false;
                print(self.isValid)
            }

            if self.checkLogin(data: responseString!) == true {
                self.performSegue(withIdentifier: "profileViewController", sender: self)
            }
            else{
                print("Hello")
                // It prints hello fine, but when it tries to run the showAlert function it fails
                self.showAlert()
            }


            //print("responseString = \(self.responseString)")

        }

        //executing the task
        task.resume()
   }

This is the alert function

/*
     * Show UIAlert Message
     */
    func showAlert() -> Void{
        let alert = UIAlertController(title: "User Does Not Exist",
                                      message: "",
                                      preferredStyle: UIAlertControllerStyle.alert)
        let loginFail = UIAlertAction(title: "Close", style: .default, handler: nil);

        alert.addAction(loginFail);
        present(alert, animated: true)

    }

This is method is called when user clicks login.

Upvotes: 0

Views: 324

Answers (1)

Duncan C
Duncan C

Reputation: 131418

Unless you take special steps, the completion handlers for the tasks you submit to NSURLSession get run on a background thread. That means that any UI calls you do must be sent to the main thread or they don't work correctly (And may crash your app.)

The code in your completion handler is doing more UI work than just invoking an alert. You're also invoking a segue. If your completion handler doesn't do time-consuming work you might want to wrap the whole thing in a GCD call to the main thread:

DispatchQueue.main.async() {
  //Put the entire body of your completion handler in here
}

Otherwise, you'll need to individually wrap each UI call in a call to the main queue like above.

EDIT:

Looking at your specific completion handler, you have one if/then/else block that does UIKit calls:

if self.checkLogin(data: responseString!) {  
  self.performSegue(withIdentifier: "profileViewController", 
    sender: self)
} else {
  print("Hello")
  self.showAlert()
}

So just wrap that part in a call to the main queue:

DispatchQueue.main.async() {
  if self.checkLogin(data: responseString!) {  
    self.performSegue(withIdentifier: "profileViewController", 
      sender: self)
  } else {
    print("Hello")
    self.showAlert()
  }
}

Upvotes: 3

Related Questions