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