How to format UITextField with NSNumberFormatter?

418 Views Asked by At

Hope this helps others, since I haven't seen any similar post on the web that shows how to format a text field using NSNumberFormatter but at the same time keep the UITextField cursor position to where it should naturally be. Those, because after formatting, the NSString from inside the UITextField and setting it back to the field you end up with the cursor placed an the end of the field. Also it will be nice to convert it to Swift for those that needs it.

1

There are 1 best solutions below

0
On

And here is my answer to the issue, I am using a UIKeyboardTypeNumberPad, but also it will work fine with a UIKeyboardTypeDecimalPad, if other keyboard types are used, feel free to add a regex before using the next code:

- (int)getCharOccurencies:(NSString *)character inString:(NSString *)string{

    NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[string length]];
    for (int i=0; i < [string length]; i++) {
        NSString *ichar  = [NSString stringWithFormat:@"%c", [string characterAtIndex:i]];
        [characters addObject:ichar];
    }

    int count = 0;
    for (NSString *ichar in characters) {
        if ([ichar isEqualToString:character]) {
            count++;
        }
    }
    return count;

}

- (void)selectTextForInput:(UITextField *)input atRange:(NSRange)range {
    UITextPosition *start = [input positionFromPosition:[input beginningOfDocument]
                                                 offset:range.location];
    UITextPosition *end = [input positionFromPosition:start
                                               offset:range.length];
    [input setSelectedTextRange:[input textRangeFromPosition:start toPosition:end]];
}

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

    NSString *charUsedToFormat = @",";

    NSMutableString *textString = [NSMutableString stringWithString:[textField text]];
    [textField setTintColor:[UIColor darkGrayColor]];

    if ([string isEqualToString:charUsedToFormat]) {
        return NO;
    }

    if (range.location == 0 && [string isEqualToString:@"0"]) {
        return NO;
    }

    if ([[textString stringByReplacingCharactersInRange:range withString:string] length] == 0) {
        textField.text = @"";
        [self selectTextForInput:textField atRange:NSMakeRange(0, 0)];
        return NO;
    }

    NSString *replacebleString = [textString substringWithRange:range];

    if (string.length == 0 && [replacebleString isEqualToString:charUsedToFormat]) {

        NSRange newRange = NSMakeRange( range.location - 1, range.length);
        range = newRange;
        textString = [NSMutableString stringWithString:[textString stringByReplacingCharactersInRange:newRange withString:string]];
    }else{
         textString = [NSMutableString stringWithString:[textString stringByReplacingCharactersInRange:range withString:string]];
    }


    int commmaCountBefore = [self getCharOccurencies:charUsedToFormat inString:textString];

    textString = [NSMutableString stringWithString:[textString stringByReplacingOccurrencesOfString:charUsedToFormat withString:@""]];
    NSNumber *firstNumber = [NSNumber numberWithDouble:[textString doubleValue]];
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
    //just in case
    [formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
    [formatter setGroupingSeparator:charUsedToFormat];
    [formatter setDecimalSeparator:@""];
    [formatter setMaximumFractionDigits:0];
    textString = [NSMutableString stringWithString:[formatter stringForObjectValue:firstNumber]];
    textField.text = textString;

    int commmaCountAfter = [self getCharOccurencies:charUsedToFormat inString:textString];
    int commaDif = commmaCountAfter - commmaCountBefore;


    int cursorPossition = (int)range.location + (int)string.length + commaDif;

    //set cursor position
    NSLog(@"cursorPossition: %d", cursorPossition);


    [self selectTextForInput:textField atRange:NSMakeRange(cursorPossition, 0)];

    return NO;

}