Format Phone Number Real-Time using NBAsYouTypeFormatter

1.3k views Asked by At

I have searched all over the place and I have seen many solutions to this, but most of it are really being "hackish" and error prone.

I am trying to format the phone number on UITextField using the libPhoneNumber iOS Class NBAsYouTypeFormatter.

However, I couldnt find a proper way of using it.

Below is my attempt. (From this thread Phone number format ios)

      var asYouTypeFormatter = NBAsYouTypeFormatter(regionCode: "US");

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if textField == phoneTextField {
        if range.length == 0 {
            textField.text = asYouTypeFormatter.inputDigit(textField.text + string);
        }
        else if range.length == 1 {
            textField.text = asYouTypeFormatter.removeLastDigit();
        }
        return false;
    }
    return true;
}

This code really detect range.length and it doesnt take into account that if the user select one or more character and then type.

If the user does that, it will resulted in it not being type.

Have anyone found a more elegant method to this problem?

1

There are 1 answers

0
Daniele Cux On
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if textField == phoneTextField {
        if range.length == 0 {
            textField.text = asYouTypeFormatter.inputDigit(textField.text + string);
        } else {
            // take the resulting string after the replacement
            var resultString = textField.text.replacingCharacters(in: range, 
                    with: replacementString)
            // prepare the string to be usable by the NBAsYouTypeFormatter
            resultString = String(string.characters.filter { "01234567890+".characters.contains($0)
            // set the result on the text field 
            textField.text = asYouTypeFormatter.inputString(resultString);
        }
        return false;
    }
    return true;
}

Note: I'm writing in objective C, I didn't test the Swift syntax, but the logic of this solution works for me;

This is my Objective-C working code:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

    NSString *resultString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    // This is to let the user clear the text field
    if ([resultString isEqualToString:@""]) { return YES; };

    NBAsYouTypeFormatter *formatter = [[NBAsYouTypeFormatter alloc] initWithRegionCode:[[NSLocale currentLocale] countryCode]];

    NSCharacterSet *allowedPhoneCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"+0123456789"];

    resultString = [[resultString componentsSeparatedByCharactersInSet:
                            [allowedPhoneCharacterSet invertedSet]]
                           componentsJoinedByString:@""];

    dispatch_async(dispatch_get_main_queue(), ^{
        textField.text = [formatter inputString:resultString];
    });

    return NO;
}