nsnumberformatter numberfromstring returns nil - objective-c

I have a string containing a pure number, but numberFromString returns nil.
Any idea why?
My code:
NSString *fText = #"33";
NSNumberFormatter *formatter;
NSNumber *fNum = [formatter numberFromString:fText];
NSLog(#"Number is %i", [fNum integerValue];
prints 0, and debugs as NIL.
Am I missing something in the formatter properties?
Thanks !

Your NSNumberFormatter is not initialized, so it is nil, and returning nil for the NSNumber.
Try:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
NSNumber* fNum = [formatter numberFromString:fText];
It should work then.

Related

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]);

Getting nil from NSNumberformater numberFromString

I'm trying to format an amount from a .txt file coming in es_US locale(x,xxx.xx), to my current locale with is es_ES(x.xxx,xx). I would expect that [NSNumberFormater numberFromString] would just reformat the string, however and I'm only getting a nil value from this method.
I also tried another approach after checking the answers from here, but NSDecimalnumber does not work if the string has thousand separators, so if anybody could tell me what am I doing wrong please...
- (void) setSaldo_sap:(NSString *)saldo_sap
{
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setLocale:[NSLocale currentLocale]];
[numFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numFormatter setNegativeFormat:#"-¤#,##0.00"];
//saldo_sap = #" -324,234.55"
NSString * tmpString = [saldo_sap stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSNumber *num = [numFormatter numberFromString:tmpString];
NSDecimalNumber *tempNumber = [NSDecimalNumber decimalNumberWithString:tmpString];
_saldo_sap = [numFormatter stringFromNumber:tempNumber];
}
I think you misinterpret the aim of NSNumberFormatter: it doesn't "reformat", it "formats" and "parses" a numbers formatted along the set rules. So if you have numbers coming in "es_US" locale but want to format them using "es_ES" you will need two NSNumberFormatters: one for each locale.
Parse the incoming number with "es_US" and format using "es_ES", simplifying a bit (I don't know those two locales and the exact format of your numbers so you may need to tweek it a bit):
NSString * tmpString = ...
NSNumberFormatter *usFormatter = [[NSNumberFormatter alloc] init];
[usFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier: #"es_US"] autorelease]];
[usFormatter setHasThousandSeparators: YES];
NSNumberFormatter *esFormatter = [[NSNumberFormatter alloc] init];
[esFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier: #"es_ES"] autorelease]];
[esFormatter setHasThousandSeparators: YES];
// this assignment looks also somewhat weird: is it an instance variable?
// 'cause if it is and you assign an autoreleased string you'll have a bad pointer there
_saldo_sap = [esFormatter stringFromNumber: [usFormatter numberFromString: tmpString]];
// And unless you use ARC you leak your formatter on each call, so at the end
[usFormatter release];
[esFormatter release];
EDIT
If the input strings contain prefix/postfix characters, that may prevent NSNumberFormatter to work (it use usually pretty strict), use setLenient::
"Sets whether the receiver will use heuristics to guess at the number which is intended by a string."
If you have more than one number to be converted, do not create the formatters for each number, this is just a waste of memory and cpu. Make them instance variables and reuse. It will be much clearer than just having one formatter and reconfiguring it between parsing one format and formatting in another.
NSString *_saldo_sap = #" -324234.55";
//NSString *_saldo_sap = #" 324,234.55";
NSString * tmpString = [_saldo_sap stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
//tmpString = #"-324,234.55"
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
NSNumber *num = [numFormatter numberFromString:tmpString];
[numFormatter setLocale:[NSLocale currentLocale]];
[numFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numFormatter setNegativeFormat:#"-¤#,##0.00"];
_saldo_sap = [numFormatter stringFromNumber:num];
Firstly, for getting NSNumber from NSString the string must be in correct readable format i.e. it must not include any characters like " , " as stated.
Secondly, you must first convert the string to NSNumber and then format it accordingly.

Need Help Rounding Numbers (Float)

In the following code, I want the the number that satisfies if (isKgs) to be rounded to one decimal point.
For example right now it is giving me 2.2643534543 but I just want 2.3.
Any ideas?
NSNumber *weightInPounds = [self.pickerArray objectAtIndex:row];
NSNumber *weightInKilos = [[DDUnitConverter massUnitConverter] convertNumber: weightInPounds fromUnit: DDMassUnitUSPounds toUnit: DDMassUnitKilograms];
NSString *temp = [NSString stringWithFormat:#"%# kgs", [weightInKilos stringValue]];
[self.firstComponentText setString:temp];
The the type of number from the picker is float, I believe.
You can format the NSNumber object using an NSNumberFormatter object. An example,
NSNumber * decimal = [NSNumber numberWithFloat:2.2643534543];
NSNumberFormatter * formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setRoundingMode:NSNumberFormatterRoundHalfUp];
[formatter setMaximumFractionDigits:1];
NSLog(#"%#", [formatter stringFromNumber:decimal]);

How to convert an NSString into an NSNumber

How can I convert a NSString containing a number of any primitive data type (e.g. int, float, char, unsigned int, etc.)? The problem is, I don't know which number type the string will contain at runtime.
I have an idea how to do it, but I'm not sure if this works with any type, also unsigned and floating point values:
long long scannedNumber;
NSScanner *scanner = [NSScanner scannerWithString:aString];
[scanner scanLongLong:&scannedNumber];
NSNumber *number = [NSNumber numberWithLongLong: scannedNumber];
Thanks for the help.
Use an NSNumberFormatter:
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
f.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber *myNumber = [f numberFromString:#"42"];
If the string is not a valid number, then myNumber will be nil. If it is a valid number, then you now have all of the NSNumber goodness to figure out what kind of number it actually is.
You can use -[NSString integerValue], -[NSString floatValue], etc. However, the correct (locale-sensitive, etc.) way to do this is to use -[NSNumberFormatter numberFromString:] which will give you an NSNumber converted from the appropriate locale and given the settings of the NSNumberFormatter (including whether it will allow floating point values).
Objective-C
(Note: this method doesn't play nice with difference locales, but is slightly faster than a NSNumberFormatter)
NSNumber *num1 = #([#"42" intValue]);
NSNumber *num2 = #([#"42.42" floatValue]);
Swift
Simple but dirty way
// Swift 1.2
if let intValue = "42".toInt() {
let number1 = NSNumber(integer:intValue)
}
// Swift 2.0
let number2 = Int("42')
// Swift 3.0
NSDecimalNumber(string: "42.42")
// Using NSNumber
let number3 = NSNumber(float:("42.42" as NSString).floatValue)
The extension-way
This is better, really, because it'll play nicely with locales and decimals.
extension String {
var numberValue:NSNumber? {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter.number(from: self)
}
}
Now you can simply do:
let someFloat = "42.42".numberValue
let someInt = "42".numberValue
For strings starting with integers, e.g., #"123", #"456 ft", #"7.89", etc., use -[NSString integerValue].
So, #([#"12.8 lbs" integerValue]) is like doing [NSNumber numberWithInteger:12].
You can also do this:
NSNumber *number = #([dictionary[#"id"] intValue]]);
Have fun!
If you know that you receive integers, you could use:
NSString* val = #"12";
[NSNumber numberWithInt:[val intValue]];
Here's a working sample of NSNumberFormatter reading localized number NSString (xCode 3.2.4, osX 10.6), to save others the hours I've just spent messing around. Beware: while it can handle trailing blanks ("8,765.4 " works), this cannot handle leading white space and this cannot handle stray text characters. (Bad input strings: " 8" and "8q" and "8 q".)
NSString *tempStr = #"8,765.4";
// localization allows other thousands separators, also.
NSNumberFormatter * myNumFormatter = [[NSNumberFormatter alloc] init];
[myNumFormatter setLocale:[NSLocale currentLocale]]; // happen by default?
[myNumFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
// next line is very important!
[myNumFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; // crucial
NSNumber *tempNum = [myNumFormatter numberFromString:tempStr];
NSLog(#"string '%#' gives NSNumber '%#' with intValue '%i'",
tempStr, tempNum, [tempNum intValue]);
[myNumFormatter release]; // good citizen
I wanted to convert a string to a double. This above answer didn't quite work for me. But this did: How to do string conversions in Objective-C?
All I pretty much did was:
double myDouble = [myString doubleValue];
Thanks All! I am combined feedback and finally manage to convert from text input ( string ) to Integer. Plus it could tell me whether the input is integer :)
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:thresholdInput.text];
int minThreshold = [myNumber intValue];
NSLog(#"Setting for minThreshold %i", minThreshold);
if ((int)minThreshold < 1 )
{
NSLog(#"Not a number");
}
else
{
NSLog(#"Setting for integer minThreshold %i", minThreshold);
}
[f release];
I think NSDecimalNumber will do it:
Example:
NSNumber *theNumber = [NSDecimalNumber decimalNumberWithString:[stringVariable text]]];
NSDecimalNumber is a subclass of NSNumber, so implicit casting allowed.
What about C's standard atoi?
int num = atoi([scannedNumber cStringUsingEncoding:NSUTF8StringEncoding]);
Do you think there are any caveats?
You can just use [string intValue] or [string floatValue] or [string doubleValue] etc
You can also use NSNumberFormatter class:
you can also do like this code 8.3.3 ios 10.3 support
[NSNumber numberWithInt:[#"put your string here" intValue]]
NSDecimalNumber *myNumber = [NSDecimalNumber decimalNumberWithString:#"123.45"];
NSLog(#"My Number : %#",myNumber);
Try this
NSNumber *yourNumber = [NSNumber numberWithLongLong:[yourString longLongValue]];
Note - I have used longLongValue as per my requirement. You can also use integerValue, longValue, or any other format depending upon your requirement.
Worked in Swift 3
NSDecimalNumber(string: "Your string")
I know this is very late but below code is working for me.
Try this code
NSNumber *number = #([dictionary[#"keyValue"] intValue]]);
This may help you. Thanks
extension String {
var numberValue:NSNumber? {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter.number(from: self)
}
}
let someFloat = "12.34".numberValue

String to int - cocoa, objective-c

I'm trying to get a value from a NSTextField (Label) and convert it to a int...
minFormatter = [[NSNumberFormatter alloc] init];
[minFormatter setNumberStyle:NSNumberFormatterNoStyle];
NSNumber *minTimeValue = [minFormatter numberFromString:[NSString stringWithFormat:#"%#", [self.minTextLabel stringValue]]];
[minFormatter release];
int minTimeValueInt;
minTimeValueInt = [minTimeValue intValue];
NSLog(#"%#", minTimeValueInt);
I can't find anything wrong with it, but the NSLog returns (null) when I log the minTimeValueInt what's wrong?
%# is the format string for an object. It's interpreting minTimeValueInt as a pointer, which is apparently 0 (null). Use %d instead.