Error With Code

Hi there,

So I posted this message in the wrong forum.
Basically I am trying to build a Custom iOS SignUp/Login Page with a longer signup process than the one Chris created in his YouTube video. When I run the app the build is successful however when I click on the signup button I am running into this error - > Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value now to errorLabel.alpha = 0. I followed basically the same format of how Chris coded his app with more text fields and instead of transitioning to the home screen, I transition to a verification code screen instead. I’m not sure if I did the “Check for errors” section part correctly. Here is the code:

@IBAction func submitTapped(_ sender: Any) {
// Validate fields

        let error = validateFields()
        
        if error != nil {
            
            //There's something wrong with the fields, show error message
            showError(error!)
            
        }
        
        else { 

        //Create cleaned version of the data
            let firstName = firstNameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
            let lastName = lastNameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
            let username = usernameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
            let email = emailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
            let phoneNumber = phoneNumberTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
            let password = passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
            

            Auth.auth().createUser(withEmail: email, password: password) {
                
                (result, err) in
                
                // Check for errors
                if err != nil {
                    
                    // There was an error creating the user
                    self.showError("There was an error creating user.")
                }
                else {
                    
                    // User was created successfully, now store all info
                    let db = Firestore.firestore()
                    db.collection("users").addDocument(data:
                        ["firstName": firstName,
                         "lastName": lastName,
                         "username": username,
                         "email": email,
                         "phoneNumber": phoneNumber,
                         "password": password,
                         "confirmedPassword": confirmedPassword,
                         "uid": result!.user.uid]) {
                            (error) in
                            // SignUp not successful
                            if error != nil {
                                //error message
                                self.showError("Error saving user data")
                            }
    
                    }
                    
                     // Transition to verification code screen
                    self.transitionToVerificationScreen()
                    
                }
            }

Any chance you know how to solve this issue? Thanks so much! x

Add some breakpoints in your code to see where exactly the Optional field is being detected as nil. Often the error messages don’t point to the exact line.

I tried that. Not sure what else to do.

Does it crash when you transition to the VerificationScreen or before that?

What does the code look like in the function
transitionToVerificationScreen()

1 Like

Hey just want to say thanks so much for helping me out!
So what’s been happening is, it crashes right when I click the signup button.
So far in the verification button, I have no code I’ve only connected the IBOutlets This is the full code for tapped.

@objc func viewTapped(gestureRecognizer: UITapGestureRecognizer){
view.endEditing(true)
}

func setUpElements() {
    
    errorLabel.alpha = 0
    
    //style the elements
    Utilities.styleTextField(firstNameTextField)
    Utilities.styleTextField(lastNameTextField)
    Utilities.styleTextField(emailTextField)
    Utilities.styleTextField(phoneNumberTextField)
    Utilities.styleTextField(passwordTextField)
    Utilities.styleTextField(confirmPasswordTextField)
    Utilities.styleHollowButton(submitButton)
        
    
}
    
func validateFields() -> String? {
        
    // Check that all fields are filled in
    if firstNameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
        lastNameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
        emailTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
        phoneNumberTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
        passwordTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
        confirmPasswordTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
        // Fields are not filled
        return "Please fill in all fields."
}
       
                
    //Check if password is secure
    let cleanedPassword = passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
    if Utilities.isPasswordValid(cleanedPassword) == false {
        // Password is not secure enough
        return "Password is invalid! Please enter a password that is at least 8 characters in length, contains a special character and a number."
            
   
    }
    
        
        return nil
        
}

    

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */
    

    
    @IBAction func submitTapped(_ sender: Any) {
        // Validate fields
        
        let error = validateFields()
        
        if error != nil {
            
            //There's something wrong with the fields, show error message
            showError(error!)
            
        }
        
        else {
            
            
            //Create cleaned version of the data
            let firstName = firstNameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
            let lastName = lastNameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
            let email = emailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
            let phoneNumber = phoneNumberTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
            let password = passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
            let confirmedPassword = confirmPasswordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
                            
            // Create user
            Auth.auth().createUser(withEmail: email, password: password){ (result, err) in
                
                // Check for errors
                if err != nil {
                    
                    // There was an error creating the user
                    self.showError("There was an error creating user.")
                }
                else {
                    
                    // User was created successfully, now store all info
                    let db = Firestore.firestore()
                    db.collection("users").addDocument(data:
                        ["firstName": firstName,
                         "lastName": lastName,
                         "email": email,
                         "phoneNumber": phoneNumber,
                         "password": password,
                         "confirmedPassword": confirmedPassword,
                         "uid": result!.user.uid ]) {
                            (error) in
                            // SignUp not successful
                            if error != nil {
                                //error message
                                self.showError("Error saving user data")
                            }
    
                    }
                    
                     // Transition to verification code screen
                    self.transitionToVerificationScreen()
                    
                }
            }
            
           
            
        }
        
        
        
    }
func showError (_ message: String) {
    
    errorLabel.text = message
    errorLabel.alpha = 1
    
}

func transitionToVerificationScreen(){
    
    let verificationViewController = storyboard?.instantiateViewController(identifier: Constants.Storyboard.verificationViewController) as?
    VerificationViewController
    
    view.window?.rootViewController = verificationViewController
    view.window?.makeKeyAndVisible()
    
    
}
    
}

I also just realized im getting the same thread 1 message in my code in setUpElements()
override func viewDidLoad() {
super.viewDidLoad()

        // Do any additional setup after loading the view.
        setUpElements()
        
        
    }

So if it crashes when you tap SignUp then the issue is the initial setup of the SignUp View Controller. Something is nil but should not be.

(edit) Just to be sure I am on the same page as you… from the opening screen when you first run the project do you have the option to SignUp or Login?

If yes, does the segue to get you to the SignUpViewController, (so that you can enter your First Name, Last Name, email, password and whatever else you want the user to enter before proceeding), actually get you to the SignUpViewController?

If Yes and you enter the details in all of the fields and then tap on the Sign Up button do you then validate all of the fields to ensure that data had been entered before you then create the User?

Actually I fixed the issue! Thanks so much for your help!
I was wondering for firebase createUser is it possible to create a user withUsername or is it just withEmail?

In the original setup of the App you are basing your project on, the method chosen for login is email and password on the Firebase side.

If you want to change it to username and password then I assume that you would delete all the current users and then change the option that suits you best.

I have not tried that so I can’t confirm that it is as simple as that. Read the Firebase documentation and see if that’s how you do it.

1 Like