letsCode
letsCode

Reputation: 3046

Check if a UITextField is characters/numbers only

I have this block of code....

let characterset = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-")
        if itemDescription.text!.rangeOfCharacter(from: characterset.inverted) != nil {
            print("string contains special characters")
            let message = MDCSnackbarMessage()
            message.text = "Numbers and letters only."
            MDCSnackbarManager.show(message)
            progressView.isHidden = true
            buttonSearchOutlet.isHidden = false
        }

No matter what I type in, I get the snackbar to show. I expect these to be false

Hello
hello
hello1
hello-

I expect this to be true

Hello!
hello's
hello1@
hello$&@#

What did I do wrong?

Upvotes: 0

Views: 147

Answers (1)

Leo Dabus
Leo Dabus

Reputation: 236275

You can simply check if all characters satisfy a condition and check if your string with the valid characters contais those characters.

extension StringProtocol {
    var isLetterDigitOrHyphen: Bool {
        allSatisfy("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-".contains)
    }
}

Usage:

let str = "Hello"
if str.isLetterDigitOrHyphen {
    print("string is ok")
} else {
    print("string contains special characters")
}

"Hello".isLetterDigitOrHyphen  // true
"hello".isLetterDigitOrHyphen  // true
"hello1".isLetterDigitOrHyphen  // true
"hello-".isLetterDigitOrHyphen  // true

"Hello!".isLetterDigitOrHyphen  // false
"hello's".isLetterDigitOrHyphen  // false
"hello1@".isLetterDigitOrHyphen  // false
"hello$&@#".isLetterDigitOrHyphen  // false

If you would like to use regular expressions:

extension StringProtocol {
    var isLetterDigitOrHyphen: Bool {
        range(of:"^[a-zA-Z0-9-]{1,}$", options: .regularExpression) != nil
    }
}

Or using a character set:

extension StringProtocol {
    var isLetterDigitOrHyphen: Bool {
        unicodeScalars.allSatisfy(CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-").contains)
    }
}

Of course you can simply negate the result if you would like to:

extension String {
    static let validCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-"
}

extension StringProtocol {
    var isNotLetterDigitOrHyphen: Bool {
        !unicodeScalars.allSatisfy(CharacterSet(charactersIn: .validCharacters).contains)
    }
}

Upvotes: 4

Related Questions