Formatting UITextField's text as Phone Number as user types in

senty picture senty · Mar 16, 2016 · Viewed 7.1k times · Source

I have a custom UITextField, which I am trying to 'format the input to phone number' as user types. What I want to achieve:

  • Adding a prefixed + sign on the UITextField as the first character, that cannot be deleted.

  • Format both the String variable and UITextField's text in the format of phone number nicely (+49 291 12345678), rather than plain numbers (4929112345678) as user types in.


I researched and found out that there is no built-in method for that. I've also found easy-to-use library called PhoneNumberKit for formatting the input String to Phone number. In Playground, it works like..

let rawNumberArray = "+4929112345678"
let phoneNumbers = PartialFormatter().formatPartial(rawNumberArray)

print(phoneNumbers) // "+49 291 12345678"

Bare in mind that, the library needs the String to have + as the first character to format properly.


I tried implementing it on my UITextField.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
    if textField == myTextField {
        let candidateString : NSString = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)
        let updatedTextString : NSString = PartialFormatter().formatPartial(candidateString as String)

        self.formattedPhoneNumber(updatedTextString, textField: textField)
    }
    return true
}

func formattedPhoneNumber(updatedTextString: NSString, textField: UITextField) {
    //  textField.text = "+\(updatedTextString as String)"
    print(updatedTextString)
}

If I keep textField.text = "+\(updatedTextString as String)" commented, print(updatedTextString) prints nicely formatted String on the console, BUT inside UITextField on UI, it just shows plain, unstructured numbers like "4929112345678"

If I uncomment it, things start to get weird and UITextField starts present duplicated characters in the UI, but console log for print also gets pretty weird. I also tried emptying textField.text = "" before, but didn't work either.


What am I doing wrong? What am I missing that doesn't let it work fine? I believe it's related with me and not the library itself.

Also, if you have any other suggestions (or libraries) for me to overcome this problem, please share them.

Answer

dichen picture dichen · Mar 16, 2016

If you are changing the values you want to show, should return false after replacing the text. Here is an example:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if let text = textField.text {
        print("curText: \(text) range: \(range.location)-\(range.length) string: \(string)" )

        let candidate = (text as NSString).stringByReplacingCharactersInRange(range, withString: string)

        if(!candidate.isCorrectFormat()){
            textField.text = callYourFormatMethodHere();

            return false
        }

    }

    return true
}

You need to implement your own isCorrectFormat() and callYourFormatMethodHere().

Edit:

Use your code:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
    if textField == myTextField {
        let candidateString : NSString = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)
        let updatedTextString : NSString = PartialFormatter().formatPartial(candidateString as String)

        self.formattedPhoneNumber(updatedTextString, textField: textField)

        return false // Return false here
    }
    return true
}