0
votes

I have a swift file used to manage the connection with Firebase (signup, signin, save data). In this file a use some AlertController to inform the user depending of message from Firebase (wrong email format, email already used). The problem is that when some alerController has to show up, they receive this message :

Warning: Attempt to present *** on *** whose view is not in the window hierarchy!

A Signup ViewController is the current view and this view is linked to another specific file. I have read a lot on "windows hierarchy" on Stackoverflow and Google in general and try different things.

I had the same issue with a similar code used for the signup. I went from this way to present the alertController :

present(alerInvalidEmail, animated: true, completion: nil)

to that one :

UIApplication.shared.keyWindow?.rootViewController?.present(alertInvalidEmail, animated: true, completion: nil)

and now it works fine but it is not working with my signup section. I suppose it is related to the current ViewController, but can not find my way.

Here my code from the networking file :

struct NetworkingService {

var databaseRef: FIRDatabaseReference! {
    return FIRDatabase.database().reference()
}
var  storageRef: FIRStorageReference! {
    return FIRStorage.storage().reference()
}


func signUp(email: String, pseudo:String, password: String, data: NSData!){

    FIRAuth.auth()?.createUser(withEmail: email, password: password, completion: { (user, error) in

        if error != nil {
            print(error!.localizedDescription)


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

            case .errorCodeInvalidEmail:
                let alertInvalidEmail =  UIAlertController(title: "Email validation", message: "You have entered an malformed adress", preferredStyle: .alert)
                alertInvalidEmail.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action:UIAlertAction) in
                    print("Invalid email")
                }))

                UIApplication.shared.keyWindow?.rootViewController?.present(alertInvalidEmail, animated: true, completion: nil)


            case .errorCodeEmailAlreadyInUse:
                let alertUsedEmail =  UIAlertController(title: "Email validation", message: "This email is already used", preferredStyle: .alert)
                alertUsedEmail.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action:UIAlertAction) in
                    print("In use")
                }))
                    UIApplication.shared.keyWindow?.rootViewController?.present(alertUsedEmail, animated: true, completion: nil)


            default:
                print("Create User Error: \(error!)")
            }}

        } else {
            self.setUserInfo(user: user, pseudo : pseudo, password: password, data: data)


            let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "nextView")

            (UIApplication.shared.keyWindow?.rootViewController?.present(vc, animated: true, completion: nil))!
            print("user signed up successfully")

        }
    })
}

and here is the code use to call the signup function from the ViewController file.

@IBAction func signUpAction(_ sender: Any) {

    let data = UIImageJPEGRepresentation(self.UserImageView.image!, 0.8)

    networkingService.signUp(email: emailTextField.text!, pseudo: pseudoTextField.text!, password: passwordTextField.text!, data: data! as NSData)

Maybe I'm not on the right window but the same code work fine for the signup section.

Thanks in advance for your help.

1

1 Answers

1
votes

Add a new parameter in your function viewController of type UIViewController

func signUp(email: String, pseudo:String, password: String, data: NSData!,viewController: UIViewController){

        FIRAuth.auth()?.createUser(withEmail: email, password: password, completion: { (user, error) in

            if error != nil {
                print(error!.localizedDescription)


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

                case .errorCodeInvalidEmail:
                    let alertInvalidEmail =  UIAlertController(title: "Email validation", message: "You have entered an malformed adress", preferredStyle: .alert)
                    alertInvalidEmail.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action:UIAlertAction) in
                        print("Invalid email")
                    }))

                    viewController.present(alertInvalidEmail, animated: true, completion: nil)


                case .errorCodeEmailAlreadyInUse:
                    let alertUsedEmail =  UIAlertController(title: "Email validation", message: "This email is already used", preferredStyle: .alert)
                    alertUsedEmail.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action:UIAlertAction) in
                        print("In use")
                    }))
                        viewController.present(alertUsedEmail, animated: true, completion: nil)


                default:
                    print("Create User Error: \(error!)")
                }}

            } else {
                self.setUserInfo(user: user, pseudo : pseudo, password: password, data: data)


                let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "nextView")

                (UIApplication.shared.keyWindow?.rootViewController?.present(vc, animated: true, completion: nil))!
                print("user signed up successfully")

            }
        })
    }

And Call it as

 networkingService.signUp(email: emailTextField.text!, pseudo: pseudoTextField.text!, password: passwordTextField.text!, data: data! as NSData, viewController: self)