16

I would like my iPhone app to allow the input, display and storage of currency amounts using the appropriate symbol ($, €, ₤, ¥, etc) for the user.

Would NSNumberFormatter do everything I need? What happens when a user switches their locale and these amounts (dollars, yen, etc.) are stored as NSDecimalNumbers. I assume, to be safe, it's necessary to somehow capture the locale at the time of entry and then the currency symbol and store them in my instance along with the NSDecimalNumber ivar so they can be unwrapped and displayed appropriately down the road should the user changed their locale since the time when the item was created?

Sorry, I have little localization experience so hoping for a couple quick pointers before diving in. Lastly, any insight on how to you handle this kind of input given the limitations of the iPhone's keyboards?

quoo
  • 6,237
  • 1
  • 19
  • 36
Meltemi
  • 37,979
  • 50
  • 195
  • 293

1 Answers1

32

NSNumberFormatter is definitely the way to go! You can set a NSLocale on the NSNumberFormatter, the formatter will automatically behave according to that locale. The default locale for a number formatter is always the currency for the users selected region format.

NSDecimalNumber *someAmount = [NSDecimalNumber decimalNumberWithString:@"5.00"];

NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];

NSLog(@"%@", [currencyFormatter stringFromNumber:someAmount]);

This will log the amount '5.00' according to the users default region format. If you want to alter the currency you can set:

NSLocale *aLocale = [[NSLocale alloc] initWithLocaleIdentifier: "nl-NL"]
[currencyFormatter setLocale:aLocale];

Which will choose the default currency for that locale.

Often though you're not charging in your user's local currency, but in your own. To force NSNumberFormatter to format in your currency, while keeping the number formatting in the user's preference, use:

currencyFormatter.currencyCode = @"USD"
currencyFormatter.internationalCurrencySymbol = @"$"
currencyFormatter.currencySymbol = @"$"

In en-US this will format as $5.00 in nl-NL it's $ 5,00.

klaaspieter
  • 2,665
  • 1
  • 27
  • 32
  • That's what I thought. I'm curious what happens when the user changes their locale after someAmount has been archived to disk. The iPhone could, quite easily, find itself in another country on a business trip. If the user is comfortable with the local language etc they may change the Locale. What happens when this object is unarchived? Will it display as '$5.00' as was created and intended, or will it display as '¥5' which, obviously, has a significantly different monetary value but is a correctly formatted NSDecimalNumber of '5.00' when the currencyFormatter's locale is Japan. – Meltemi May 13 '09 at 16:32
  • You can store someAmount formatted or unformatted. If you store it formatted, the amount will always reflect the currency it was made in. If you store it unformatted, the formatter will just format it in the current locale, but will not do any conversion! Thus: '$5.00' will become '¥5'. What I do in my app is store both the unformatted currency and it's locale. This way I am always sure that the currency is formatted in the locale it was made in, but I can also add currency conversion later on. – klaaspieter May 14 '09 at 08:40
  • just by c/p'ing this code, i get the warning: format not a string literal and no format arguments Can i not get this? – oberbaum Jan 19 '10 at 14:59
  • @norskben - Try `NSLog(@"%@",[[currencyFormatter stringFromNumber:someAmount] description]);` – Moshe Jun 24 '10 at 19:28
  • @norskben - Apple changed the behavior of NSLog without a format argument to throw a warning at some point. My code was written before that point. I corrected the code, it should work without warning now. – klaaspieter Jul 05 '10 at 12:00
  • This doesn't seem to be working in the iOS8 simulator in XCode 6.1.1 - whatever region I set, I'm getting USD from the currentLocale. Works fine on an iOS8 device though. – Echelon Jan 20 '15 at 09:42
  • @Navi `aLocale` is probably something like this: `NSLocale *aLocale = [NSLocale currentLocale];` – CyberMew Jan 09 '17 at 07:18