Nicos Karalis
Nicos Karalis

Reputation: 3773

Custom format for a NSNumber to NSString conversion

I have on my application a UITextField that receives a number.

I want that this number to be represented in a particular format, like this: (62) 1234 1234

The problem is: i already have control over the method -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string but i dont know how can i make this "mask"

Currently i`m doing like this:

string = [textField.text stringByReplacingCharactersInRange:range withString:string];
string = [[string componentsSeparatedByCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]] componentsJoinedByString:@""];

NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:string];
NSLog(@"%@", myNumber);

at the end of this code i have 2 things:

  1. string : the string representation of my text ( e.g. 6212341234 as a NSString )
  2. myNumber : the number for this string ( e.g. 6212341234 as a NSNumber )

how can i create this string: (62) 1234 1234 based on myNumber or string ?

EDIT

Responding to rdelmar question:

The number can have 10 or 11 numbers, and i intent to separate them like this: (62) 1234 1234 or (62) 12345 1234

Upvotes: 0

Views: 612

Answers (2)

rsswtmr
rsswtmr

Reputation: 1816

You could use NSRegularExpression...

- (NSString *) formattedString:(NSString *)inputString
{
    NSError *error = NULL;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(?:([0-9]{2})([0-9]{5})([0-9]{4}))|(?:([0-9]{0,2}+)([0-9]{0,4}+)([0-9]{0,4}+))" options:0 error:&error];
    NSArray *components = [NSArray array];
    NSArray *matches = [regex matchesInString:inputString options:0 range:NSMakeRange(0, [inputString length])];
    NSTextCheckingResult *match = [matches objectAtIndex:0];
    for ( NSUInteger i = 1; i <= 3; ++i )
    {
        NSRange range = [match rangeAtIndex:i];
        if ( NSNotFound == range.location )
        {
            break;
        }
        components = [components arrayByAddingObject:[inputString substringWithRange:range]];
    }
    if ( 0 == [components count] )
    {
        for ( NSUInteger i = 4; i <= 6; ++i )
        {
            NSRange range = [match rangeAtIndex:i];
            components = [components arrayByAddingObject:[inputString substringWithRange:range]];
        }
    }
    return [NSString stringWithFormat:@"(%@) %@ %@",
            [components objectAtIndex:0],
            [components objectAtIndex:1],
            [components objectAtIndex:2]];
}


- (void) testFormatting
{
    NSLog(@"%@", [self formattedString:@"62123451234"]);
    NSLog(@"%@", [self formattedString:@"6212341234"]);
    NSLog(@"%@", [self formattedString:@"621234123"]);
    NSLog(@"%@", [self formattedString:@"62123412"]);
    NSLog(@"%@", [self formattedString:@"6212341"]);
    NSLog(@"%@", [self formattedString:@"621234"]);
    NSLog(@"%@", [self formattedString:@"62123"]);
    NSLog(@"%@", [self formattedString:@"6212"]);
    NSLog(@"%@", [self formattedString:@"621"]);
    NSLog(@"%@", [self formattedString:@"62"]);
    NSLog(@"%@", [self formattedString:@"6"]);
}

The result of calling the testFormatting method is:

(62) 12345 1234
(62) 1234 1234
(62) 1234 123
(62) 1234 12
(62) 1234 1
(62) 1234 
(62) 123 
(62) 12 
(62) 1 
(62)  
(6)  

This way you could pass intermediate strings to the formatter and it would try to do the right thing.

Upvotes: 1

rdelmar
rdelmar

Reputation: 104082

You could do it something like this (for 10 digit numbers):

-(NSString *)formatString:(NSString *) input {
    NSString *part1 = [NSString stringWithFormat:@"(%@)",[input substringToIndex:2]];
    NSString *part2 = [input substringWithRange:NSMakeRange(2, 4)];
    NSString *part3 = [input substringWithRange:NSMakeRange(6, 4)];
    NSString *formatted = [NSString stringWithFormat:@"%@ %@ %@",part1,part2,part3];
    return formatted;

}

To handle 10 or 11 digit numbers you would have to put in an if clause to test the length, and then change the ranges of part2 and part3 accordingly.

After Edit: How about something like this. I think this is about as good as can be done. It will break it into (xx) xxxx xxxx as you type, and if you type another digit it will break it into (xx) xxxxx xxxx. Any further input is ignored.

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField.text.length == 0)
     textField.text = [NSString stringWithFormat:@"(%@",textField.text];

    if (textField.text.length == 3)
        textField.text = [NSString stringWithFormat:@"%@) ",textField.text];

    if (textField.text.length == 9)
        textField.text = [NSString stringWithFormat:@"%@ ",textField.text];

    if (textField.text.length == 14) {
        NSString *part1 = [textField.text substringToIndex:9];
        part1 = [part1 stringByAppendingString:[textField.text substringWithRange:NSMakeRange(10, 1)]];
        NSString *part2 = [textField.text substringWithRange:NSMakeRange(11, 3)];
        textField.text = [NSString stringWithFormat:@"%@ %@",part1,part2];
    }

    if (textField.text.length > 14)
        return NO;

    return YES;
}

Upvotes: 0

Related Questions