0

Is there a way to auto format a phone number easily? I want to have my user to just enter the number and for it to format like (###)-###-####, or at least locking my keypad to a phone pad. The app is for internal use on iPads so I know that setting the keyboard to numberpad in the attribute inspector wont do anything.

I am on a time restraint so the most time effective advice would be great. I was initially going to validate the textfield with a regex but different users put numbers different from my recent tests with a small group in the company. Some put ###.###.####, some put ### ### #### and some put (###)-###-#### so it was just annoying.

user3443430
  • 67
  • 1
  • 7

1 Answers1

0

I've used something similar to this with good results, and the format will be (###) ###-#### x###... It likely isn't the most blazingly efficient process, but for all intents and purposes it does the job pretty well.

Assuming you have a property/instance variable for your textField, as well as a BOOL to track whether or not you want to allow it to be formatted, here is how I've implemented it. When I create my textField for the phone number, I do the following:

self.textField.keyboardType = UIKeyboardTypeNumberPad;
self.textField.delegate = self;
[self.textField addTarget:self action:@selector(formatPhoneNumber) forControlEvents:UIControlEventEditingChanged];

The above makes the keyboard the number pad, and any time the value is changed we call formatPhoneNumber, also make sure to implement the UITextFieldDelegateProtocol and set yourself as the field's delegate.

Then, we implement the shouldChangeCharactersInRange method,

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    // this is what the textField's string will be after changing the characters
    NSString *resultString = [textField.text stringByReplacingCharactersInRange:range withString:string];

    // flag that we should attempt to format the phone number ONLY if they are adding
    // characters, otherwise if they are deleting characters we simply want to allow
    // them to delete them and not format them
    _shouldAttemptFormat = resultString.length > self.textField.text.length;

    return YES;
}

The format phone number method will only attempt to format the number if we determined that we should in shouldChangeCharactersInRange method, breaks up the current text into the useful phone number pieces, like (555) 444-2222 -> 5554442222, and then formats it nicely:

- (void)formatPhoneNumber {
    // this value is determined when textField shouldChangeCharactersInRange is called on a phone
    // number cell - if a user is deleting characters we don't want to try to format it, otherwise
    // using the current logic below certain deletions will have no effect
    if (!_shouldAttemptFormat) {
        return;
    }

    // here we are leveraging some of the objective-c NSString functions to help parse and modify
    // the phone number... first we strip anything that's not a number from the textfield, and then
    // depending on the current value we append formatting characters to make it pretty
    NSString *currentString = self.textField.text;
    NSString *strippedValue = [currentString stringByReplacingOccurrencesOfString:@"[^0-9]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, currentString.length)];

    NSString *formattedString;
    if (strippedValue.length == 0) {
        formattedString = @"";
    }
    else if (strippedValue.length < 3) {
        formattedString = [NSString stringWithFormat:@"(%@", strippedValue];
    }
    else if (strippedValue.length == 3) {
        formattedString = [NSString stringWithFormat:@"(%@) ", strippedValue];
    }
    else if (strippedValue.length < 6) {
        formattedString = [NSString stringWithFormat:@"(%@) %@", [strippedValue substringToIndex:3], [strippedValue substringFromIndex:3]];
    }
    else if (strippedValue.length == 6) {
        formattedString = [NSString stringWithFormat:@"(%@) %@-", [strippedValue substringToIndex:3], [strippedValue substringFromIndex:3]];
    }
    else if (strippedValue.length <= 10) {
        formattedString = [NSString stringWithFormat:@"(%@) %@-%@", [strippedValue substringToIndex:3], [strippedValue substringWithRange:NSMakeRange(3, 3)], [strippedValue substringFromIndex:6]];
    }
    else if (strippedValue.length >= 11) {
        formattedString = [NSString stringWithFormat:@"(%@) %@-%@ x%@", [strippedValue substringToIndex:3], [strippedValue substringWithRange:NSMakeRange(3, 3)], [strippedValue substringWithRange:NSMakeRange(6, 4)], [strippedValue substringFromIndex:10]];
    }

    self.textField.text = formattedString;
}

Here's a video of it in action just now:

https://www.dropbox.com/s/xq9vb9p62oamova/phone.mov?dl=0

I use something similar in my open-source project that handles iOS forms, if you want to reference more code related to this. The first link is to the gif with the demo so you can see it in action.

https://raw.githubusercontent.com/mamaral/MAFormViewController/master/Screenshots/form_demo.gif https://github.com/mamaral/MAFormViewController

Mike
  • 9,765
  • 5
  • 34
  • 59