3

I'm currently working on a project where I use lots of UITextFields. For validation I need to check if the UITextFields are empty. I got a working solution, but it's not that elegant. Maybe someone knows a better way of doing it.

Here is my solution:

// Check if text field is empty
if let text = textField.text, !text.isEmpty {
     // Text field is not empty
} else {
     // Text field is empty
}

Is there a faster way without unwrapping the text attribute of the text field to find out if it's empty?

Thanks!

Lars Petersen
  • 602
  • 9
  • 21
  • 1
    Stick an extension on UITextField that does it for you :) – Woodstock Sep 02 '18 at 17:25
  • if !(textField.text?.isEmpty)! {} else {} – Kwright02 Sep 02 '18 at 17:30
  • 1
    Various solutions at [How to check if a text field is empty or not in swift](https://stackoverflow.com/questions/24102641/how-to-check-if-a-text-field-is-empty-or-not-in-swift) and [Checking if textfields are empty Swift](https://stackoverflow.com/questions/38162602/checking-if-textfields-are-empty-swift/38162721) – Martin R Sep 02 '18 at 17:33
  • https://developer.apple.com/documentation/uikit/uikeyinput/1614457-hastext – Leo Dabus Sep 02 '18 at 18:32
  • 1
    Note that the default value of the UITextField text property is an emptyString. You can safely force unwrap it. Even if you set it to nil before accessing its value it will never return nil – Leo Dabus Sep 02 '18 at 18:34

4 Answers4

7

You can use UIKeyInput property hasText. It works for both UITextField and UITextView:

if textField.hasText {
    // Text field is not empty
} else {
    // Text field is empty
}

If you would like to check if the text has not only spaces on it:

extension UITextField {
    var isEmpty: Bool {
        return text?.trimmingCharacters(in: .whitespacesAndNewlines) == ""
    }
}

let tf = UITextField()
tf.text = " \n \n "
tf.isEmpty   // true
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
6

How about extending UITextField

extension UITextField {

    var isEmpty: Bool {   
        if let text = textField.text, !text.isEmpty {
             return false
        } 
        return true
    }
}

so then…

if myTextField.isEmpty {
}
Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
2

If you have several textfields that you want to check, you could put them all in a guard statement

guard let text1 = textField1.text, let text2 = textField2.text, let text3 = textField3.text, !text1.isEmpty, !text2.isEmpty, !text3.isEmpty else {
    //error handling
    return
}

//Do stuff
Elhoej
  • 741
  • 7
  • 29
0

I like to validate each text field depending on the content that should be provided by the user, i.e. emailTextField should contain a valid email address etc. While Ashley Mills answer is convenient, if you regard whitespace " " as text this will return false.

In your case, since you need to validate multiple text fields in the same way, why not extend UITextField as Ashley did with a static class method that can validate each text field passed as an array, in addition to this have other validation methods for each type of text field. Instead of returning a Boolean value I've learned to use guard instead. In this way guard let can be used to check if the validation fails (is nil) and execute the proper code, such as displaying a prompt to the user, or otherwise continue execution.

UITextFieldExtension.swift

import Foundation
import UIKit

extension UITextField {

    /// Validates all text field are non-nil and non-empty, Returns true if all fields pass.
    /// - Returns: Bool
    static func validateAll(textFields:[UITextField]) -> Bool {
        // Check each field for nil and not empty.
        for field in textFields {
            // Remove space and new lines while unwrapping.
            guard let fieldText = field.text?.trimmingCharacters(in: .whitespacesAndNewlines) else {
                return false
            }
            // Are there no other charaters?
            if (fieldText.isEmpty) {
                return false
            }

        }
        // All fields passed.
        return true
    }


    //A function that validates the email address...
    func validateEmail(field: UITextField) -> String? {
        guard let trimmedText = field.text?.trimmingCharacters(in: .whitespacesAndNewlines) else {
            return nil
        }

        //email addresses are automatically detected as links in i0S...
        guard let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) else {
            return nil
        }

        let range = NSMakeRange(0, NSString(string: trimmedText).length)
        let allMatches = dataDetector.matches(in: trimmedText,
                                              options: [],
                                              range: range)

        if allMatches.count == 1,
            allMatches.first?.url?.absoluteString.contains("mailto:") == true
        {
            return trimmedText
        }
        return nil
    }

    func validateUserName(field: UITextField) -> String? {

        guard let text:String = field.text else {
            return nil
        }

        /* 3 to 12 characters, no numbers or special characters */
        let RegEx = "^[^\\d!@#£$%^&*<>()/\\\\~\\[\\]\\{\\}\\?\\_\\.\\`\\'\\,\\:\\;|\"+=-]+$"
        let Test = NSPredicate(format:"SELF MATCHES %@", RegEx)
        let isValid = Test.evaluate(with: text)

        if (isValid) {
            return text
        }

        return nil
    }

    /*6 to 16 Characters */
    func validatePassword(field: UITextField) -> String?{
        guard let text:String = field.text else {
            return nil
        }
        /*6-16 charaters, and at least one number*/
        let RegEx = "^(?=.*\\d)(.+){6,16}$"
        let Test = NSPredicate(format:"SELF MATCHES%@", RegEx)
        let isValid = Test.evaluate(with: text)

        if (isValid) {
            return text
        }

        return nil

    }
}

Meanwhile, elsewhere...

if (UITextField.validateAll(textFields: [emailTextField, nameTextField])) {
    // Do something
}
RLoniello
  • 2,309
  • 2
  • 19
  • 26