NSNumberFormatter numberFromString returns null

11,099

What is price? Assuming it's an ivar, do not access ivars directly. Always use accessors except in dealloc and init.

Assuming price is a string, why are you doing this:

[NSString stringWithFormat:@"%@", price]

If price is an NSNumber, then you can use it directly.

You're creating an NSNumber here, assigning it to amount, and then immediately throwing it away. You then over-release amount. So you should expect the above code to crash. (Because of a quirk in how NSNumber objects are managed, this crash will happen the next time you create an NSNumber for the integer 5.)

And getting all the way around to your actual question, the reason amount is nil is because "5" is not in the current currency format, so the number formatter rejected it. If you are in the US and set price to "$5.00" then it would work.


If you're really trying to convert a string to US$, then this is how to do it. Note that locale matters here. If you use the default locale, then in France "1.25" will be €1.25, which is not the same as $1.25.

You should always us NSDecimalNumber when holding currancy. Otherwise you're subject to binary/decimal rounding errors.

The following uses ARC.

NSString *amountString = @"5.25";
NSDecimalNumber *amountNumber = [NSDecimalNumber decimalNumberWithString:amountString];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];

NSNumberFormatter *currencyStyle = [[NSNumberFormatter alloc] init];    
[currencyStyle setNumberStyle:NSNumberFormatterCurrencyStyle];
[currencyStyle setLocale:locale];
NSString *currency = [currencyStyle stringFromNumber:amountNumber];

NSLog(@"%@", currency);

A more complete class for managing localized currency (RNMoney) is available in the example code for chapter 13 of iOS 5 Programming Pushing the Limits.

Share:
11,099
Hackmodford
Author by

Hackmodford

By day, I work for DornerWorks as a Mobile Applications Dev... you get the idea. By night, I am the creator of Undulib, the audiobook player for audio drama enthusiast. I also developed the BigFinish App for Big Finish Productions.

Updated on June 04, 2022

Comments

  • Hackmodford
    Hackmodford almost 2 years

    Here's my code

    NSNumberFormatter *currencyStyle = [[NSNumberFormatter alloc] init];
    
        [currencyStyle setFormatterBehavior:NSNumberFormatterBehavior10_4];
        [currencyStyle setNumberStyle:NSNumberFormatterCurrencyStyle];
    
        NSNumber *amount = [[NSNumber alloc] init];
    
        NSLog(@"the price string is %@", price);
    
        amount = [currencyStyle numberFromString:price];
    
        NSLog(@"The converted number is %@",[currencyStyle numberFromString:price]);
        NSLog(@"The NSNumber is %@", amount);
    
        NSLog(@"The formatted version is %@", [currencyStyle stringFromNumber:amount]);
    
        NSLog(@"--------------------");
        self.priceLabel.text = [currencyStyle stringFromNumber:amount]; 
    
        [amount release];
        [currencyStyle release];
    

    This is what the log spits out

    the price string is 5 The converted number is (null) The NSNumber is (null) The formatted version is (null)

    Am I missing something?

    EDIT: Updated code

    NSNumberFormatter *currencyStyle = [[NSNumberFormatter alloc] init];
        [currencyStyle setFormatterBehavior:NSNumberFormatterBehavior10_4];
        [currencyStyle setNumberStyle:NSNumberFormatterCurrencyStyle];
    
        NSNumber *amount = [currencyStyle numberFromString:price];
    
        NSLog(@"the price string is %@", price);
        NSLog(@"The converted number is %@",[currencyStyle numberFromString:price]);
        NSLog(@"The NSNumber is %@", amount);
        NSLog(@"The formatted version is %@", [currencyStyle stringFromNumber:amount]);
        NSLog(@"--------------------");
    
        self.priceLabel.text = [NSString stringWithFormat:@" %@ ", [currencyStyle stringFromNumber:amount]]; 
    
        [currencyStyle release];
    
  • Hackmodford
    Hackmodford over 12 years
    Wow... so all I had to do was format the price string to include a $ at the beginning and it works fine... My whole goal in the code was to convert a string (example 1.25) into a currency ($1.25) is there a better way to do this?