I have a number stored in an NSMutableString
instance which I want to auto format with comma delimiters and then display the result in a UITextField
.
I've tried using NSNumberFormatter
to format as currency, but I don't want it to show decimals if the original NSMutableString
doesn't contain a decimal place.
For example:
NSMutableString
contains "1234567", it should format as "1,234,567".NSMutableString
contains "1234567.1", it should format as "1,234,567.1"NSMutableString
contains "1234567.12", it should format as "1,234,567.12"The maximum decimals that the NSMutableString
will contain is 2.
Any help is greatly appreciated.
Thanks!
Keep in mind that you should really be localizing this if you are interacting with users on this, however here is one way to do it:
- (NSString *)formatString:(NSString *)string {
// Strip out the commas that may already be here:
NSString *newString = [string stringByReplacingOccurrencesOfString:@"," withString:@""];
if ([newString length] == 0) {
return nil;
}
// Check for illegal characters
NSCharacterSet *disallowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet];
NSRange charRange = [newString rangeOfCharacterFromSet:disallowedCharacters];
if ( charRange.location != NSNotFound) {
return nil;
}
// Split the string into the integer and decimal portions
NSArray *numberArray = [newString componentsSeparatedByString:@"."];
if ([numberArray count] > 2) {
// There is more than one decimal point
return nil;
}
// Get the integer
NSString *integer = [numberArray objectAtIndex:0];
NSUInteger integerDigits = [integer length];
if (integerDigits == 0) {
return nil;
}
// Format the integer.
// You can do this by first converting to a number and then back to a string,
// but I would rather keep it as a string instead of doing the double conversion.
// If performance is critical, I would convert this to a C string to do the formatting.
NSMutableString *formattedString = [[NSMutableString alloc] init];
if (integerDigits < 4) {
[formattedString appendString:integer];
} else {
// integer is 4 or more digits
NSUInteger startingDigits = integerDigits % 3;
if (startingDigits == 0) {
startingDigits = 3;
}
[formattedString setString:[integer substringToIndex:startingDigits]];
for (NSUInteger index = startingDigits; index < integerDigits; index = index + 3) {
[formattedString appendFormat:@",%@", [integer substringWithRange:NSMakeRange(index, 3)]];
}
}
// Add the decimal portion if there
if ([numberArray count] == 2) {
[formattedString appendString:@"."];
NSString *decimal = [numberArray objectAtIndex:1];
if ([decimal length] > 0) {
[formattedString appendString:decimal];
}
}
return formattedString;
}
// Test cases:
NSLog(@"%@", [self formatString:@"123456"]);
NSLog(@"%@", [self formatString:@"1234567."]);
NSLog(@"%@", [self formatString:@"12345678.1"]);
NSLog(@"%@", [self formatString:@"123456789.12"]);
// Output:
123,456
1,234,567.
12,345,678.1
123,456,789.12
I think this should do it -- I added an if statement to check if there is a decimal point in the typed in value. "Output" in this example is a property that I have bound to the value of a text field to show the result.
-(IBAction)doConversion:(id)sender{
NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
[formatter setMaximumFractionDigits:2];
[formatter setUsesGroupingSeparator:YES];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
double entryFieldFloat = [entryField doubleValue];
if ([entryField.stringValue rangeOfString:@"."].length == 1) {
formatter.alwaysShowsDecimalSeparator = YES;
self.output =[formatter stringFromNumber:[NSNumber numberWithDouble:entryFieldFloat]];
}else{
formatter.alwaysShowsDecimalSeparator = NO;
self.output =[formatter stringFromNumber:[NSNumber numberWithDouble:entryFieldFloat]];
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With