Reputation: 1558
Note: As I've posted this question, it's night time here in my place. If I haven't responded to comments or answers, I'll do it in the morning. Thank you for your understanding :-)
The idea is to format UILabel as phone number (US Format) as the user touches each UIButton.
There is a keypad layout and as the user touches each numeric key, the label displays it and at formats the resulting string on the fly. I have written a piece of code which I am not very proud of. I hope someone could help me in doing this in much better way or different approach.
The image should give you a fair idea of how it looks like. Now, getting to the logic:
In the code below, keyOne is the IBAction to append the numbers to UILabel, keyBack is the one to delete it.
So this is how it works for entering a phone number:
If I enter 1234567890:
after 1,2,3 the label is modified as 123- and gets assigned to string
Now string will be 123- and I continue touching 4567890
after 123-4567, when I touch 8, label is modified as (123)456-78 and gets assigned to string
Now string will be (123)456-7890
If I wish, I could continue entering more numbers.
As per requirement, the number should lose its formatting.
i.e. After (123)456-7890 if I press 1, it should become 12345678901
Now, the trick is to undo the steps in exact same way. Here is the pickle. If I entered only 1234567890, _phoneNumber.text would be (123)456-7890 and pressing back three times should result in 123-4567. Then pressing back four times should result in 123
However, if I entered 12345678901, _phoneNumber.text would go to (123)456-7890, then lose formatting to become 12345678901 and when I press back once, it should become (123)456-7890 and so on.
If you whip up a new project of type single view application and paste the stuff below, (of course after creating buttons and connecting 0-9 with keyOne, back with keyBack) you would see that it works fine. But as I mentioned above, I have written a piece of code which I am not very proud of. I feel there should be a simpler way to do this.
ViewController.h
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UILabel *lengthParam;
@property (weak, nonatomic) IBOutlet UILabel *phoneNumber;
- (IBAction)keyOne:(id)sender;
- (IBAction)keyBack:(id)sender;
- (IBAction)clearAll:(id)sender;
@end
ViewController.m
#import "ViewController.h"
@interface ViewController () {
BOOL isReformatted;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (IBAction)keyOne:(id)sender {
UIButton *btn = (UIButton *)sender;
NSString *str = [NSString stringWithString:self.phoneNumber.text];
str = [str stringByAppendingString:btn.titleLabel.text];
self.phoneNumber.text = str;
if(str.length==4) self.phoneNumber.text = [self insertMinus:str]; //before the 4th number, insert '-' as a first step
if(str.length==9) self.phoneNumber.text = [self insertParenthesis:str]; //remove - before the 4th number, encapsulate first 3 numbers inside () and add - at end of current number
if(str.length>13) self.phoneNumber.text = [self plainFormat:str]; //if user enter more than 10 numbers, remove formatting
self.lengthParam.text = [NSString stringWithFormat:@"%d",self.phoneNumber.text.length];
}
- (IBAction)keyBack:(id)sender {
NSString *str = [NSString stringWithString:self.phoneNumber.text];
NSString *newStr = nil;
if(str.length>0) { //check for empty string
if(str.length>11 && isReformatted==NO) newStr = [str substringToIndex:str.length-1]; //string.length > 10 which means plainFormat was called earlier and reFormat isn't called yet
else if(str.length==11 && isReformatted == NO) { //string length is now 11
if([str characterAtIndex:0]!='(') newStr = [self reFormat:str]; //if entered string is 12345678901, it is not reFormatted. remove last 1 and reFormat it as (123)456-7890
else newStr = [self removeParenthesis:str]; //entered string itself is (123)456-78 so transform it as 123-4567
} else { //we are dealing with a reformatted string of length 11 now.
newStr = [str substringToIndex:str.length-1]; //String is (123)456-78, remove 8 and apply one of the below rules
if(newStr.length==10) { //transform (123)456-7 as 123-4567
newStr = [str substringToIndex:str.length-1];
newStr = [self removeParenthesis:str];
}
if(newStr.length==4&&[newStr characterAtIndex:3]=='-') newStr = [self removeMinus:str]; //transform 123-4 to 123
}
self.phoneNumber.text = newStr;
self.lengthParam.text = [NSString stringWithFormat:@"%d",self.phoneNumber.text.length];
}
}
- (IBAction)clearAll:(id)sender {
self.phoneNumber.text = @"";
self.lengthParam.text = [NSString stringWithFormat:@"%d",self.phoneNumber.text.length];
}
- (NSString *)insertMinus:(NSString *)str {
return [NSString stringWithFormat:@"%@-%@",[str substringToIndex:3],[str substringFromIndex:3]];
}
- (NSString *)insertParenthesis:(NSString *)str {
NSString *c1 = [NSString stringWithFormat:@"(%@)",[str substringToIndex:3]];
NSString *c2 = [NSString stringWithFormat:@"%@-%@",[str substringWithRange:NSMakeRange(4, 3)],[str substringFromIndex:7]];
return [NSString stringWithFormat:@"%@%@",c1,c2];
}
- (NSString *)plainFormat:(NSString *)str {
isReformatted = NO;
str = [str stringByReplacingOccurrencesOfString:@"(" withString:@""];
str = [str stringByReplacingOccurrencesOfString:@")" withString:@""];
str = [str stringByReplacingOccurrencesOfString:@"-" withString:@""];
str = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
return str;
}
- (NSString *)reFormat:(NSString *)str {
isReformatted = YES;
NSString *c1 = [NSString stringWithFormat:@"(%@)",[str substringToIndex:3]];
NSString *c2 = [NSString stringWithFormat:@"%@-%@",[str substringWithRange:NSMakeRange(3, 3)],[str substringWithRange:NSMakeRange(6, 4)]];
return [NSString stringWithFormat:@"%@%@",c1,c2];
}
- (NSString *)removeParenthesis:(NSString *)str {
str = [self plainFormat:str];
NSString *newStr = [NSString stringWithFormat:@"%@-%@",[str substringToIndex:3],[str substringWithRange:NSMakeRange(3, 4)]];
return newStr;
}
- (NSString *)removeMinus:(NSString *)str {
str = [self plainFormat:str];
NSString *newStr = [NSString stringWithFormat:@"%@",[str substringToIndex:3]];
return newStr;
}
@end
Upvotes: 0
Views: 1272
Reputation: 18922
If you are eager to go down the road of rolling your own phone number formatter, I would consider doing the follow:
Something like:
@property (nonatomic, copy) NSMutableString *backingString;
@property (weak, nonatomic) IBOutlet UILabel *phoneNumber;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
backingString = [NSMutableString string];
}
- (IBAction)keyOne:(id)sender
{
UIButton *btn = (UIButton *)sender;
[self.backingString appendString:btn.titleLabel.text];
[self formatBackingString];
}
- (IBAction)keyBack:(id)sender
{
[self.backingString deleteCharactersInRange:(NSRange){self.backingString.length - 1,1}];
[self formatBackingString];
}
- (void)formatBackingString
{
// Do your phone formatting here
NSMutableString *formattedString = [NSMutableString string];
NSInteger length = self.backingString.length;
if (length < 3)
{
[formattedString appendString:self.backingString];
}
else if (length == 3)
{
[formattedString appendFormat:@"%@-", self.backingString];
}
else if (length < 8)
{
// etc...
}
self.phoneNumber.text = formattedString;
}
You could also look at NSNumberFormatter.
Upvotes: 1