Search code examples
swiftgrand-central-dispatchcompletionhandlerios-multithreading

Returning from threading/ GCD/ completion handler


I have some logic to sign a user in from a login screen. If the login fails, I want to display a message to let the user know. If the user logs in successfully, I trigger a segue. When I test it with invalid credentials, the error alert displays as expected but the segue is still being triggered even though it's nested in an if-else statement. Why is this? How can I return out of it and avoid the else block...? I tried adding 'return' under the DispatchQ/ show alert code and that didn't have any effect.

self.login(username: usernameTextField.text!, password: passwordTextField.text!) { (error) in
        if error != nil {
            DispatchQueue.main.async {
                self.showAlert(msg: error ?? "error")
            }
        } else {
            DispatchQueue.main.async {
                // segue code
            }
        }
    }

login:

func login(username: String, password: String, completionHandler: @escaping (_ error: String?) -> ()) {
    SessionHelper.shared.logUserIn(withUsername: username, andPassword: password) { (error) in
        if let err = error {
            completionHandler(err)
        }
        completionHandler(nil)
    }
}

Solution

  • You're running the completion handler either way; if you get an error back, you're calling it, but then you fall through and run it with nil. Try this:

    func login(username: String, password: String, completionHandler: @escaping (_ error: String?) -> ()) {
    SessionHelper.shared.logUserIn(withUsername: username, andPassword: password) { (error) in
        if let err = error {
            completionHandler(err)
        } else {
            completionHandler(nil)
        }
    }
    

    }