-1

I have setup a UITextField in a ViewController and Xcode doesn't show me errors. But when I run my app and load the Screen the app crashes with the error message:

Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

This is my code:

import Foundation
import UIKit

class LoginScreenViewController: UIViewController, UITextFieldDelegate{
    
    @IBOutlet weak var phoneAndEmailTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        phoneAndEmailTextField.delegate = self
        passwordTextField.delegate = self
    }

    @IBAction func phoneAndEmailTextFieldAction(_ sender: UITextField) {
        phoneAndEmailTextField.endEditing(true)
        print(phoneAndEmailTextField.text!)
    }

    @IBAction func passwordTextFieldAction(_ sender: UITextField) {
        passwordTextField.endEditing(true)
        print(passwordTextField.text!)
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        phoneAndEmailTextField.endEditing(true)
        passwordTextField.endEditing(true)
        
        return true
    }

    func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
        if textField.text != "" {
            return true
        }else {
            return false
        }
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
        // sql
    }
}

This is are the referenced Outlets of one TextField. The other one is the same... Storyboard

David
  • 63
  • 6
  • there is probably no text in your textfields and force unwrapping them like this `print(phoneAndEmailTextField.text!)` and `print(passwordTextField.text!)` is what is causing your crash probably. Safely unwrap them prior to printing and see if your crashes get resolved. – Shawn Frank Feb 15 '22 at 13:04
  • But the View doesn't even load. The crash is at the delegate when I try to load the view, so the print statements doesn't get triggered. – David Feb 15 '22 at 13:22
  • Find which line causes the iissue: `phoneAndEmailTextField.delegate = self`? Then `phoneAndEmailTextField` is nil, and you wrote that it shouldn't with `UITextField!`. Question is how did you load/created `LoginScreenViewController`? Did you connected correctly the IBOutlets in Storyboard/Xib? – Larme Feb 15 '22 at 13:44
  • Which specific line is crashing? – Duncan C Feb 15 '22 at 14:01
  • The phoneAndEmailTextField.delegate = self gets the crash. I also though about connecting the IBOutlets could be the issue but I deleted them and reconnected them a few times... – David Feb 15 '22 at 14:06
  • Edit your question to include that information. People reading this thread should not have to wade through a whole series of comments to understand your question fully. – Duncan C Feb 15 '22 at 14:10
  • Then, how is shown `LoginScreenViewController`? How is it created? Did you write `LoginScreenViewController()`? Instead of initializing it from the storyboard? – Larme Feb 15 '22 at 14:36
  • I've just presenting it with present(LoginScreenViewController(), animated: true) – David Feb 15 '22 at 14:38
  • So you are doing indeed `LoginScreenViewController()`. And how should it know that it needs to be linked with that specific storyboard? What if there was another storyboard with a similar one, but with different colors? So you need to instatiante the storybooard, then the viewcontroller from it. See https://stackoverflow.com/questions/24035984/instantiate-and-present-a-viewcontroller-in-swift – Larme Feb 15 '22 at 14:44
  • Does this answer your question? [Instantiate and Present a viewController in Swift](https://stackoverflow.com/questions/24035984/instantiate-and-present-a-viewcontroller-in-swift) – Larme Feb 15 '22 at 14:44
  • No, it still crashes... I have the Storyboard linked via class... – David Feb 15 '22 at 14:54
  • @Larme, good guess on the call to LoginScreenViewController’s default initializer. You should either post that as an answer, or mark the question as a duplicate pointing to the link you posted above. – Duncan C Feb 15 '22 at 14:55
  • DO NOT USE CALLS TO `MyViewController()` (or `LoginScreenViewController()` in your case) to create your view controller from a storyboard. That won’t work. – Duncan C Feb 15 '22 at 14:56
  • @DuncanC I flagged it as a duplicate. But I don't have enough rights to close it at once, others have to flagged it also. And the wrong init without linking the storyboard/xib is the second best guess after ibtoulet not connected. – Larme Feb 15 '22 at 14:57
  • @Larme Do you have a thread that specifically says "Don't use `MyViewController()` initializer to load view controllers from a Storyboard?" That would be a better choice for a duplicate to link to. – Duncan C Feb 15 '22 at 15:04
  • Maybe https://stackoverflow.com/questions/53387373/iboutlet-nil-button – Larme Feb 15 '22 at 15:09
  • @David What's your new code with Storyboard instantiation first? Is the crash the same one? – Larme Feb 15 '22 at 15:10
  • @Larme thanks man that worked – David Feb 15 '22 at 15:35

1 Answers1

0

In your textFieldShouldReturn(_:) method, you reference both phoneAndEmailTextField and passwordTextField. They are both declared as implicitly unwrapped optionals, meaning if either of those outlets is not connected in your storyboard, that function will crash.

Try rewriting that function like this:

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    guard let phoneAndEmailTextField = phoneAndEmailTextField else {
        print("phoneAndEmailTextField is nil")
        return false
    }
    guard let passwordTextField = passwordTextField else {
        print("passwordTextField is nil")
        return false
    }

    
    phoneAndEmailTextField?.endEditing(true)
    passwordTextField?.endEditing(true)
    
    return true
}

(Note that with implicitly unwrapped optionals, if you reference them with a question mark as I did in the edited version of your function, the compiler will still do optional chaining and skip the function call/property reference if the thing being referenced is nil.)

Edit:

If it's the statement phoneAndEmailTextField.delegate = self that's crashing, that tells you that phoneAndEmailTextField is nil. You must be doing something wrong in hooking up your IBOutlets. Add a screenshot of your view controller to your question with the connections inspector shown so we can see the connections of those two outlets.

You could fix the crash by rewriting the line as phoneAndEmailTextField?.delegate = self but the phoneAndEmailTextField outlet will still be nil, so you will only be patching the problem, not fixing it.

BTW, you can connect your text field delegates to your view controller right in your storyboard. Just select the text field, pick the connections inspector, and drag from the delegate connection onto the view controller in the storyboard.

Duncan C
  • 122,346
  • 22
  • 162
  • 258
  • But this doesn't resolve the issue because the Screen will never appear because of the crash. So it crashes before the screen loads... – David Feb 15 '22 at 14:12
  • See the edit to my answer. I posted it before you told us what line was crashing. When asking about a crash, alway include info about the line that's crashing your question. – Duncan C Feb 15 '22 at 14:13
  • Okay, sure forgot it. Edited with the picture of the IBOutlets. I also tried to connect directly with the delegate but this doesn't want to let me drag and drop... – David Feb 15 '22 at 14:23