Handling Errors in New Firebase and Swift

2019-01-31 14:25发布

问题:

I'm trying to add error handling in creating user button in iOS project using swift and firebase:

Here's the code for the button:

     @IBAction func Register(sender: AnyObject) {

    if NameTF.text == "" || EmailTF.text == "" || PasswordTF.text == "" || RePasswordTF == "" || PhoneTF.text == "" || CityTF.text == ""
    {
        let alert = UIAlertController(title: "عذرًا", message:"يجب عليك ملىء كل الحقول المطلوبة", preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "نعم", style: .Default) { _ in })
        self.presentViewController(alert, animated: true){}

    } else {

        if PasswordTF.text != RePasswordTF.text {
            let alert = UIAlertController(title: "عذرًا", message:"كلمتي المرور غير متطابقتين", preferredStyle: .Alert)
            alert.addAction(UIAlertAction(title: "نعم", style: .Default) { _ in })
            self.presentViewController(alert, animated: true){}

        } else {


            FIRAuth.auth()?.createUserWithEmail(EmailTF.text!, password: PasswordTF.text!, completion: { user, error in
                print(error)

                if error != nil {

                    let errorCode = FIRAuthErrorNameKey

                    switch errorCode {
                    case "FIRAuthErrorCodeEmailAlreadyInUse":
                        let alert = UIAlertController(title: "عذرًا", message:"الإيميل مستخدم", preferredStyle: .Alert)
                        alert.addAction(UIAlertAction(title: "نعم", style: .Default) { _ in })
                        self.presentViewController(alert, animated: true){}

                    case "FIRAuthErrorCodeUserNotFound":
                        let alert = UIAlertController(title: "عذرًا", message:"المستخدم غير موجود", preferredStyle: .Alert)
                        alert.addAction(UIAlertAction(title: "نعم", style: .Default) { _ in })
                        self.presentViewController(alert, animated: true){}

                    case "FIRAuthErrorCodeInvalidEmail":
                        let alert = UIAlertController(title: "عذرًا", message:"الإيميل غير صحيح", preferredStyle: .Alert)
                        alert.addAction(UIAlertAction(title: "نعم", style: .Default) { _ in })
                        self.presentViewController(alert, animated: true){}

                    case "FIRAuthErrorCodeNetworkError":
                        let alert = UIAlertController(title: "عذرًا", message:"خطأ في الاتصال بالانترنت", preferredStyle: .Alert)
                        alert.addAction(UIAlertAction(title: "نعم", style: .Default) { _ in })
                        self.presentViewController(alert, animated: true){}

                    default:
                        let alert = UIAlertController(title: "عذرًا", message:"خطأ غير معروف", preferredStyle: .Alert)
                        alert.addAction(UIAlertAction(title: "نعم", style: .Default) { _ in })
                        self.presentViewController(alert, animated: true){}



                    }


                } else {

                    FIRAuth.auth()?.signInWithEmail(self.EmailTF.text!, password: self.PasswordTF.text!, completion: { (user: FIRUser?, error: NSError?) in
                        if let error = error {
                            print(error.localizedDescription)
                        } else {

                           self.ref.child("UserProfile").child(user!.uid).setValue([
                                "email": self.EmailTF.text!,
                                "name" : self.NameTF.text!,
                                "phone": self.PhoneTF.text!,
                                "city" : self.CityTF.text!,
                                ])
                            print("Sucess")
                          //  self.performSegueWithIdentifier("SignUp", sender: nil)

                        }
                    })

                } //else
            })

        } //Big else


    } //Big Big else
}


}//end of

I'm not sure if the syntax of the errors in switch statement is correct or not!

Because when I tested it in the simulator it always gives me the defualt case which is unknown error! + I could not find the syntax in the documentation: https://firebase.google.com/docs/auth/ios/errors

So, What's the correct syntax to add error handling using new firebase and swift!

回答1:

I've actually just struggled with this for quite a bit of time and found what the issue was. I've tried the code posted in an answer above and the error.code line gave me an error. It did work with error._code though. In other words, credit for the original answer to Paul with a slight modificaiton. Here's my final code (I will edit it for all errors though):

if let errCode = FIRAuthErrorCode(rawValue: error!._code) {

    switch errCode {
        case .errorCodeInvalidEmail:
            print("invalid email")
        case .errorCodeEmailAlreadyInUse:
            print("in use")
        default:
            print("Create User Error: \(error)")
    }    
}


回答2:

Updated for Swift 4 + Firebase 4 + UIAlertController

extension AuthErrorCode {
    var errorMessage: String {
        switch self {
        case .emailAlreadyInUse:
            return "The email is already in use with another account"
        case .userNotFound:
            return "Account not found for the specified user. Please check and try again"
        case .userDisabled:
            return "Your account has been disabled. Please contact support."
        case .invalidEmail, .invalidSender, .invalidRecipientEmail:
            return "Please enter a valid email"
        case .networkError:
            return "Network error. Please try again."
        case .weakPassword:
            return "Your password is too weak. The password must be 6 characters long or more."
        case .wrongPassword:
            return "Your password is incorrect. Please try again or use 'Forgot password' to reset your password"
        default:
            return "Unknown error occurred"
        }
    }
}


extension UIViewController{
    func handleError(_ error: Error) {
        if let errorCode = AuthErrorCode(rawValue: error._code) {
            print(errorCode.errorMessage)
            let alert = UIAlertController(title: "Error", message: errorCode.errorMessage, preferredStyle: .alert)

            let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil)

            alert.addAction(okAction)

            self.present(alert, animated: true, completion: nil)

        }
    }

}

Usage example:

    Auth.auth().signIn(withEmail: email, password: password, completion: { (user, error) in

        if error != nil {
            print(error!._code)
            self.handleError(error!)      // use the handleError method
            return
        }
        //successfully logged in the user

    })


回答3:

Even though this has been answered correctly, wanted to share a nice implementation for this we added to our project.

This can be done for other error types as well, but we just needed it for the FIRAuthErrorCodes.

If you extend FIRAuthErrorCode to have a variable errorMessage of type string, you can have your own error messages for the users:

extension FIRAuthErrorCode {
    var errorMessage: String {
        switch self {
        case .errorCodeEmailAlreadyInUse:
            return "The email is already in use with another account"
        case .errorCodeUserDisabled:
            return "Your account has been disabled. Please contact support."
        case .errorCodeInvalidEmail, .errorCodeInvalidSender, .errorCodeInvalidRecipientEmail:
            return "Please enter a valid email"
        case .errorCodeNetworkError:
            return "Network error. Please try again."
        case .errorCodeWeakPassword:
            return "Your password is too weak"
        default:
            return "Unknown error occurred"
        }
    }
}

You could customize only some as we have above and group the rest under "Unknown error".

With this extension you can handle an error as shown in Vladimir Romanov's answer:

func handleError(_ error: Error) {
    if let errorCode = FIRAuthErrorCode(rawValue: error._code) {
        // now you can use the .errorMessage var to get your custom error message
        print(errorCode.errorMessage)
    }
}


回答4:

FIRAuthErrorCode is an int enum not a string enum. Do the following:

if let error = error {
        switch FIRAuthErrorCode(rawValue: error.code) !{
                case .ErrorCodeInvalidEmail:

More info in this answer.