Search code examples
iosswiftfirebasefirebase-authenticationcompletion

Swift - Firebase function signInWithEmail don't execute in the first call


@IBAction func loginEmailButton(sender: AnyObject) {
        FIRAuth.auth()?.signInWithEmail(email.text!, password: password.text!, completion: { (user, error) in
            if error != nil {
                if let errCode = FIRAuthErrorCode(rawValue: error!.code) {
                    switch errCode {
                    case .ErrorCodeInvalidEmail:
                        self.emailLoginStatus = "invalid email"
                    case .ErrorCodeUserDisabled:
                        self.emailLoginStatus = "User account disabled"
                    case .ErrorCodeWrongPassword:
                        self.emailLoginStatus = "Wrong Password"
                    case .ErrorCodeUserNotFound:
                        self.emailLoginStatus = "User not found"
                    case .ErrorCodeNetworkError:
                        self.emailLoginStatus = "Could not connect"
                    default:
                        self.emailLoginStatus = "Login Error"
                    }
                }
            }else{
                self.emailLoginStatus = "Logged"
            }
        })

        if self.emailLoginStatus == "Logged"{
            self.performSegueWithIdentifier("emailLoginToSearchSegue", sender: self)
        }else{
            showAlert(emailLoginStatus)
        }

}

I did debug the code step by step and this is the situation: When I tap the loginEmailButton for the first time, the email and password parameters are set to signInWithEmail function, but this function doesn't execute (the next step on debug goes directly out of function without run the completion block).

Then the simulator shows the alert message without text, but if I close the alert and tap the loginEmailButton again, the signInWithEmail is executed correctly and shows the alert with the correct message. I even tried updating the Firebase pods but the problem still remains.

Any suggestion? Thanks!


Solution

  • Its asynchronous issue. signInWithEmail makes an asynchronous call to the server, meaning this call will be loaded in a different network thread, which takes some time to complete, but since your performSegueWithIdentifier is put outside the completionBlock so it get's executed even before sign In could be completed, But when you press your button next time your users had been previously been signed in from your first call, so it segues...

    Just put the

    self.performSegueWithIdentifier("emailLoginToSearchSegue", sender: self)
    

    inside the signInWithEmail completionBlock().

    @IBAction func loginEmailButton(sender: AnyObject) {
        FIRAuth.auth()?.signInWithEmail(email.text!, password: password.text!, completion: { (user, error) in
            if error != nil {
                if let errCode = FIRAuthErrorCode(rawValue: error!.code) {
                    switch errCode {
                    case .ErrorCodeInvalidEmail:
                        self.emailLoginStatus = "invalid email"
                    case .ErrorCodeUserDisabled:
                        self.emailLoginStatus = "User account disabled"
                    case .ErrorCodeWrongPassword:
                        self.emailLoginStatus = "Wrong Password"
                    case .ErrorCodeUserNotFound:
                        self.emailLoginStatus = "User not found"
                    case .ErrorCodeNetworkError:
                        self.emailLoginStatus = "Could not connect"
                    default:
                        self.emailLoginStatus = "Login Error"
                    }
                }
            }else{
                self.performSegueWithIdentifier("emailLoginToSearchSegue", sender: self)
            }
        })
    }