Format values from a NSArray - objective-c

I have a NSArray containing several strings that look like this: "291839.0930820"
I would like to format those values in the array so that they show up in my detailTextLabel of a UITableView with only 2 decimals: "291,839.09"
How can I accomplish this?

To properly format numbers so the numbers appear correctly for a given user's domain is to use NSNumberFormatter. You should never usevstringWithFormat: for such purposes.
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]:
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setMaximumFractionDigits:2];
NSNumber *val = array[indexPath.row];
NSString *text = [formatter stringFromNumber:val];
Update:
I'm getting the feeling from Juan that the array doesn't actually contain NSNumber objects for the numbers but it actually contains NSString representations of the numbers. If this is the case, then one line in my answer needs to be changed. Change:
NSNumber *val = array[indexPath.row];
to:
NSNumber *val = #([array[indexPath.row] doubleValue]);
This will get the NSString from the array, then get the string's value as a double, and finally wrap the double in an NSNumber.

You could try something like this if your array has float values
cell.detailTextLabel.text=[NSString stringWithFormat:#"%.02f", [[array objectAtIndex:index]floatValue]];

lets say your value is double value = 291839.0930820;
You can construct a string like this
NSString *formattedValue = [NSString stringWithFormat:#"%0.2f",value];
assign this formattedValue to your textfield/label.
cell.textLabel.text = formattedValue;

Related

What's the intended way to turn a NSString into a NSDecimalNumber with two decimal places?

I'm currently using the following methodology to turn a NSString number (like #"123.456") into a NSDecimalNumber after rounding (like 123.46), but it feels hacky. Is there a more intended solution?
+ (NSDecimalNumber*)decimalNumberForString:(NSString*)str accuracy:(NSUInteger)accuracy
{
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterNoStyle;
formatter.maximumFractionDigits = accuracy;
formatter.roundingMode = NSNumberFormatterRoundHalfUp;
NSNumber *numberVersion = [formatter numberFromString:str];
return [[NSDecimalNumber alloc] initWithDecimal:numberVersion.decimalValue];
}
Take a look at NSDecimalNumberHandler and NSDecimalNumber's
-decimalNumberByRoundingAccordingToBehavior:
method.
You can create a NSDecimalNumber with your unedited string, then create a new NSDecimal number that's rounded according to the rules you set on NSDecimalNumberHandler.
There's no need to edit your input string.
Use [NSDecimalNumber decimalNumberWithString:], like this:
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:#"123.456"];
The number of decimal places only affects the string representation of the number; once the number is stored in an NSDecimalNumber object it can be formatted back to a string in any way you desire.

Using NSNumber to sort numerous integers

Ive been doing alot of research and can't quite grasp resolving this issue. In my application I have several text fields that save integer values in the form of int variables (at least 15 int variables). My main goal is to sort out high to low numbers that were saved from the text fields.
Now would I use the following code to convert each seperate integer variable into a new NSNumber, than use a sort function to sort out the new NSNumbers from high to low?
NSNumber *newNumber = [NSNumber numberWithInt: my_int_variable];
I just feel as if this is a redundant way of sorting 12 integer variables and there is a easier way. Thank you for the help
Going from individual text fields to strings to ints to NSNumbers to an array to a sorted array is long, clunky trip. But a worthwhile trip nevertheless.
// assume these
UITextField *field0;
UITextField *field1;
UITextField *field2;
// make an array for the input and the result
NSArray *textFields = #[field0, field1, field2];
NSMutableArray *numbers = [#[] mutableCopy];
// prepare a number formatter
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
// lots of choices here. see https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSNumberFormatter_Class/index.html
for (UITextField *textField in textFields) {
NSString *text = textField.text;
NSNumber *number = [formatter numberFromString:text];
[numbers addObject:number];
}
// sort...a few choices here, too. taking the simplest:
[numbers sortUsingSelector:#selector(compare:)];
NSLog(#"ta da: %#", numbers);
Or did you want to sort the text fields based on their contents? Doable too:
NSMutableArray *textFields = [#[field0, field1, field2] mutableCopy];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
[textFields sortedUsingComparator: ^(id objA, id objB) {
NSString *textA = ((UITextField *)objA).text;
NSString *textB = ((UITextField *)objB).text;
NSNumber *numberA = [formatter numberFromString:textA];
NSNumber *numberB = [formatter numberFromString:textB];
return [numberA compare:numberB];
}];
NSLog(#"text fields in order of their contents: %#", textFields);

How do I combine a char with an int in an NSTextField in Objective-C?

For example, I have the following code, where lblPercent is an NSTextField:
double Progress = progress( Points);
[lblPercent setIntValue:(Progress)];
I set it as integer value so it tosses out the decimal, since for some reason the NSProgressIndicator forces me to use a double. Anyway, in the label adjacent to the progress bar, I want it see the number x% with the percent sign next to it.
I tried standard concatenation techniques but no dice.
You should use an NSNumberFormatter with the percent style
NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle: NSNumberFormatterPercentStyle];
// Any other format settings you want
NSString* formattedNumber = [formatter stringFromNumber: [NSNumber numberWithDouble: progress]];
try
[lblPercent setText:[NSString stringWithFormat:#"%d%%",[Progress intValue]]];
NSMutableString *value = lblPercent.text;
[value appendString:#"%"];
[lblPercent setText:value];
You can use unicode characters to get the percent sign.
i.e.
double value;
myLabel.text = [NSString stringWithFormat:#"%d\u0025", value ]
u0025 is the unicode character for 'percent sign'
NSInteger percentageProgress = (NSInteger) (Progress * 100);
[lblPercent setText:[NSString stringWithFormat:#"%d%%", percentageProgress]];
NSString *string = [NSString stringWithFormat:#"%.0f%#",Progress, #"%"];
[lblPercent setStringValue:string];
This seems to had worked for me doing it the way I had done it...

Convert array of NSStrings to array of formatted NSNumbers

I have an array of strings called valuesArray containing values like this: 2913451.0938
I am trying to format those numbers so that I can display them like this: 2,913,451.09
Using the following code I am able to read the values from the array and convert them to NSNumbers (num), and I am also able to create a formatter to define how I want my numbers to be displayed (formatter).
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setMaximumFractionDigits:2];
NSNumber *num = valuesArray[indexPath.row];
NSLog(#"num: %#",num);
NSLog(#"Formatter: %#",formatter);
NSString *forNum = [formatter stringFromNumber:num];
NSLog(#"FormattedNum: %#",forNum);
When I run the code and get to the line NSLog(#"FormattedNum: %#",forNum); I see that it prints null. What am I missing?
The problem in your code is that you retrieve an element from you array of strings valueArray but assign it to an NSNumber typed variable—while the object really is an NSString. When you pass it to the formatter it returns nil (even though it also might crash, it's just undefined behavior).
You have to convert the string to an NSNumber:
NSNumber *num = #([valuesArray[indexPath.row] doubleValue]);
I just checked this code with this value :
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setMaximumFractionDigits:2];
NSNumber *num = #(2913451.0938);
NSLog(#"num: %#",num);
NSLog(#"Formatter: %#",formatter);
NSString *forNum = [formatter stringFromNumber:num];
NSLog(#"FormattedNum: %#",forNum);
It worked fine, no error what so ever as you mentioned.
See the Output :
2013-02-28 21:35:44.417 BrowserModal[4861:403] num: 2913451.0938
2013-02-28 21:35:44.418 BrowserModal[4861:403] Formatter: <NSNumberFormatter: 0x100160840>
2013-02-28 21:35:44.419 BrowserModal[4861:403] FormattedNum: 29,13,451.09
Please clean your target and re-build.
And
Make sure valuesArray[indexPath.row] returns a boxed NSNumber object.
Do as : #([valuesArray[indexPath.row] doubleValue]);

NSNumberFormatter is not returning a sensible answer when converting a string

I have a UITextField, which I am trying to use a NSNumberFormatter with a NSNumberFormatterDecimalStyle to convert the text field into an NSNumber to initialise an object.
However when I do this, I can't get any sensible results out of the conversion. For the purpose of this example I have replaced the UITextField with a string, but I still get strange results. I am sure I am doing something daft, but any help would be appreciated.
//NSString * boardNumberText = self.txtBoardNumbs.text;
NSString * boardNumberText = #"42";
NSNumberFormatter * formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * boardNumber = [formatter numberFromString:boardNumberText];
if ([boardNumber isEqual:nil]) {
NSLog(#"Number was null");
}
NSLog(#"Number was not null");
[self.board setNumber:boardNumber];
NSLog(boardNumberText);
NSLog([NSString stringWithFormat:#"%d", boardNumber]);
NSLog([NSString stringWithFormat:#"%d", self.board.number]);
The output that I get from the log file when I run this is:
2012-07-15 16:54:26.564 CoreDataDev[16123:fb03] Number was not null
2012-07-15 16:54:26.564 CoreDataDev[16123:fb03] 42
2012-07-15 16:54:26.565 CoreDataDev[16123:fb03] 135821152
2012-07-15 16:54:26.565 CoreDataDev[16123:fb03] 135820272
You can't just log NSNumber to the console using the integer format specifier, since NSNumber is a wrapper object. Also, NSLog takes a format string, so you don't need to use stringWithFormat:. Try this instead:
NSLog(#"%d", [boardNumber intValue]);
Using
NSLog(#"%d", boardNumber);
is wrong: it prints the memory address of the boardNumber pointer (the NSNumber instance itself). Use
NSLog(#"%d", [boardNumber intValue]);
instead.
P. s.: that
NSLog([NSString stringWithFormat:...]);
is unnecessary and ugly; NSLog has built-in format string handling, use it!