1

Here is a UIBarButtonItem I have:

@IBAction func doneButtonPressed(_ sender: UIBarButtonItem) {
    print("doneButton Pressed")
    // Guard statement ensures that all fields have been satisfied, so that the JumpSpotAnnotation can be made, and no values are nil
    guard let name = nameTextField.text,
        let estimatedHeight = estimatedHeightTextField.text,
        let locationDescription = descriptionTextView.text else {
            nameRequiredLabel.isHidden = false
            heightRequiredLabel.isHidden = false
            descriptionRequiredLabel.isHidden = false
            print("User did not put in all the required information.")
            return
           }

The code below it in the IBAction is irrelevant since this is a guard let problem. It won't trigger even when I literally set the values to nil. In my viewDidLoad I put:

    nameTextField.text = nil
    estimatedHeightTextField.text = nil
    descriptionTextView.text = nil

And when I press the button, without changing the values of these texts, the guard let statement still doesn't trigger, and the rest of the function below executes. Any ideas why? Thanks.

  • 1
    Debug and print each values individually? – Larme Aug 18 '20 at 15:58
  • Just did and it prints Optional("") for all three. Im confused tho, I thought the whole point of a guard let was that it can't be nil. What am I doing wrong/misunderstanding? –  Aug 18 '20 at 16:04
  • They are empty if they print `Optional("")`, not nil. So you should test for the first one `guard let name = nameTextField.text, !name.isEmpty else { ... }` – Larme Aug 18 '20 at 16:10
  • @Larme thanks, that worked. appreciate it –  Aug 18 '20 at 16:17
  • UITextField text property default value is an emptyString. It will NEVER return nil even if you assign nil to it before checking its value. BTW UIKeyInput protocol has a property called `hasText` exactly for this purpose. – Leo Dabus Aug 18 '20 at 17:43

2 Answers2

2

If you are just checking that the text field is empty then you can do something like:

guard 
    let estimatedHeight = estimatedHeightTextField.text, 
    !estimatedHeight.isEmpty, 
    let locationDescription = descriptionTextView.text,
    !locationDescription.isEmpty 
    else {
        nameRequiredLabel.isHidden = false
        heightRequiredLabel.isHidden = false
        descriptionRequiredLabel.isHidden = false
        print("User did not put in all the required information.")
        return
    }

Checkout out this answer: https://stackoverflow.com/a/24102758/12761873

JTODR
  • 318
  • 2
  • 10
0

UITextField text property default value is an emptyString. It will NEVER return nil even if you assign nil to it before checking its value. BTW UIKeyInput protocol has a property called hasText exactly for this purpose. If you would like also to avoid the user entering only whitespaces and new lines you can trim them before checking if it is empty. You can extend UITextInput and implement your own isEmpty property. This would cover for UITextField and UITextView with a single implementation:

extension UITextInput {
    var isEmpty: Bool {
        guard let textRange = self.textRange(from: beginningOfDocument, to: endOfDocument) else { return true }
        return text(in: textRange)?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == true
    }
}

let textField = UITextField()
textField.text = " \n "
textField.isEmpty   // true

let textView = UITextView()
textView.text = " \n a"
textView.isEmpty   // true
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571