Formatting UITextField's text as Phone Number

2020-07-26 11:42发布

问题:

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.

回答1:

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
}