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