1

I am currently trying to validate a name input field. For that purpose I would like to check the input.

The input is a string and should only consist of letters and spaces. Is there any simple way to implement it.

For example I have the Input of "Jon Doe", how can I verify that this a acceptable name while Peter2or Ben&Jerryisnt?

Thanks for your help in advance. <3

  • 1
    You need to clarify what you want... you say `Jon Doe` is valid, but `Peter2` is not? So then, is `I am Jon Doe` valid? Or do you want ***exactly*** two alpha-only "words" with one space between? – DonMag Mar 12 '20 at 15:40
  • 3
    How about “José”? Or “田中”? Or “Chris O’Dowd”? – Rob Mar 12 '20 at 15:42

4 Answers4

12
let lettersAndSpacesCharacterSet = CharacterSet.letters.union(.whitespaces).inverted

let testValid1 = "Jon Doe".rangeOfCharacter(from: lettersAndSpacesCharacterSet) == nil // true
let testInvalid1 = "Ben&Jerry".rangeOfCharacter(from: lettersAndSpacesCharacterSet) == nil // false
let testInvalid2 = "Peter2".rangeOfCharacter(from: lettersAndSpacesCharacterSet) == nil // false
Goergisn
  • 617
  • 4
  • 15
1

you could also do something like this

func onlyLettersChecker(string: String) -> Bool {

    let justLettersRegex = "[^A-Za-zÀ-ÖØ-öø-ÿ]"

    let trimmedString = string.replacingOccurrences(of: " ", with: "")
    return trimmedString.isEmpty == false && trimmedString.range(of: justLettersRegex, options: .regularExpression) == nil
}

You delete the whitespaces of your string, and then check if there are only letters there.

That regex accepts accents in the names, you might need to modify the regex if you need some apostrophes in your names and so on.

0

Depending on the exact requirements, RegEx may be the better route.

  • Are leading / trailing / extra spaces valid?
  • Are extended Latin characters valid?
  • Are punctuated names valid (hyphenated or apostrophes)?

For example, with this list of "name" entries:

    "Jon Doe",
    "Ben&Jerry",
    "JonDoe",
    "Jon Edward Doe",
    " Jon Doe",
    "Jon   Doe",
    "Jon Doe ",
    "Jon Doe2",
    "José Doe",
    "Jon O'Doe",
    "Jon Doe-Smith",
    "Joß Müller",
    "Jon 黒澤明"

Which ones should be valid?

EDIT: updated with better (?) RegEx based on Rob's answer...

Using this code, which evaluates the entries with both .rangeOfCharacter and with a RegEx test:

class ViewController: UIViewController {

    override func viewDidLoad() {

        let names: [String] = [
            "Jon Doe",
            "Ben&Jerry",
            "JonDoe",
            "Jon Edward Doe",
            " Jon Doe",
            "Jon   Doe",
            "Jon Doe ",
            "Jon Doe2",
            "José Doe",
            "Jon O'Doe",
            "Jon Doe-Smith",
            "Joß Müller",
            "Jon 黒澤明",
        ]

        names.forEach {
            test($0)
        }

    }

func test(_ text: String) -> Void {

        let ss = "^[\\p{L}\\p{P}]+\\s[\\p{L}\\p{P}]+$"

        let b1 = text.range(of: ss, options: .regularExpression) != nil

        let lettersAndSpacesCharacterSet = CharacterSet.letters.union(.whitespaces).inverted

        let b2 = text.rangeOfCharacter(from: lettersAndSpacesCharacterSet) == nil

        print("RegEx:", b1, "\t", "Range:", b2, "\t", "[\(text)]")

    }

}

The output is:

RegEx: true      Range: true     [Jon Doe]
RegEx: false     Range: false    [Ben&Jerry]
RegEx: false     Range: true     [JonDoe]
RegEx: false     Range: true     [Jon Edward Doe]
RegEx: false     Range: true     [ Jon Doe]
RegEx: false     Range: true     [Jon   Doe]
RegEx: false     Range: true     [Jon Doe ]
RegEx: false     Range: false    [Jon Doe2]
RegEx: true      Range: true     [José Doe]
RegEx: true      Range: false    [Jon O'Doe]
RegEx: true      Range: false    [Jon Doe-Smith]
RegEx: true      Range: true     [Joß Müller]
RegEx: true      Range: true     [Jon 黒澤明]
DonMag
  • 69,424
  • 5
  • 50
  • 86
0

You have to decide how permissive you want to be. There are common Western exceptions including:

  • double-barreled names (“Daniel Day-Lewis”);
  • accents (“José Mourinho”);
  • apostrophes (“Chris O’Dowd”);
  • abbreviations for lineage (“Martin Luther King Jr.”), titles (“Dr. Li Wenliang”), and credentials (“John Nash, Ph.D.”)

Plus, if you eventually localized the app for other languages, you might want

  • non-Western character sets (“黒澤明”)

Regex handles this stuff gracefully, e.g. this is for any letter and a few select punctuation symbols:

let searchString = #"^([\p{L},.'’-]+(\s|$))+"#

if string.range(of: searchString, options: .regularExpression) != nil {
    print(string, "passed")
} else {
    print(string, "failed")
}

If you don’t want to permit the periods or commas, feel free to remove them from the above regex.

Rob
  • 415,655
  • 72
  • 787
  • 1,044