Search code examples
swiftasynchronousnsurlrequestnsoperationqueue

Correct asynchronous Authentication while keeping a responsive UI


What it's supposed to be I have a username field. When the username is entered and the sendButton is clicked, the userdata is fetched with a asynchronousRequest as a JSON file. After the sendButton is clicked, I want to display an ActivityIndicator. The UI shall still be responsive, while the request is made.

How it is now I click the sendButton and the UI freezes. Even the ActivityIndicator does NOT get displayed.

The code

LoginVC:

func buttonTouchedUpInside(sender: UIButton) {
  toggleActivityIndicatorVisibilityOn(true) 
  LoginManager.sharedInstance.checkUserForCredentials(username: textFieldLogin.text, password: "")       
  toggleActivityIndicatorVisibilityOn(false)
}

func loginManagerDidFinishAuthenticationForUser(userData: [String:String]?){
    //  Delegate Method, which works with the fetched userData.
}

LoginManager

func checkUserForCredentials(#username: String ,password: String) -> Void {
  let url = NSURL(string: "\(Config.checkCredentialsUrl)username=\(username)")
  let request = NSURLRequest(URL: url!)
  NSURLConnection.sendAsynchronousRequest(request, queue: .mainQueue()) { (response, data, error) -> Void in
    if error != nil {
      //Display error-message
    }
  var error : NSError?
  let json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &error) as? [String:String]
  self.delegate?.loginManagerDidFinishAuthenticationForUser(json)      
  }
}

In short: I want the request to be made in background, that the Activityindicator is shown and the UI stays responsive. After the asynchronous request successfully fetched the json, the delegate method shall be called


Solution

  • The second line of code in the buttonTouchedUpInside method, which reads LoginManager.sharedInstance.checkUserForCredentials(username: textFieldLogin.text, password: "") is calling an asynchronous function within it, which means that it is not blocking the next line of code... which is the one that (I am guessing) triggers your loading screen to become invisible again.

    Basically, your loading screen is showing up, but it is immediately being hidden again. To fix at least the part with your loading screen, put the third line of code in the buttonTouchedUpInside function in the callback method loginManagerDidFinishAuthenticationForUser instead.