On the iPhone:
Using the US locale, a currency looks like this: $1,234.56
Using the UK locale, a currency looks like this: £1,234.56
Using the German (Germany) locale, a currency looks like this: 1.234,56 €
and finally, a Japanese currency: ¥1,234
The Japanese currency has no decimals and this impacts my custom keyboard significantly. I'm trying to find a method in the Cocoa-touch framework which will tell me how many decimal places a specific currency has - my hard-coded value of 2 isn't doing me justice :(
Can anyone help?
You should be able to use the CFNumberFormatter objects to get the information you need. Specifically you could use CFNumberFormatterGetDecimalInfoForCurrencyCode:
CFStringRef localeIdent = CFSTR("JPY");
int numDecimals;
double rounding;
BOOL result = CFNumberFormatterGetDecimalInfoForCurrencyCode(localeIdent, &numDecimals, &rounding);
I hope that helps.
I haven't programmed in Cocoa for ages, but from the documentation for NSNumberFormatter, there's a function called 'currencyDecimalSeparator' - that might at least tell you if a currency has one at all, which might be a start?
Financial companies maintain databases of this kind of information. You might be able to buy the data or import it from an online source.
Note also: some currencies need three or four decimal places. See http://www.londonfx.co.uk/ccylist.html for examples.
I had a similar problem but the answers above didn't really solve my problem.
I ended up using the maximumFractionDigits method on NSNumberFormatter which gave me 0 for Japanese locale. Make sure you use a NSNumberFormatterCurrencyStyle for the formatter, otherwise you'll see decimal places in other formatters.
NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setLocale:[NSLocale currentLocale]];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSLog(#"Number of decimal places %i", [currencyFormatter maximumFractionDigits]);
Related
I want to be able to make the app change depending on the users location. Im using the code below:
NSLocale *locale = [NSLocale autoupdatingCurrentLocale];
NSString *countryCode = [locale objectForKey: NSLocaleCountryCode];
NSString *countryName = [locale displayNameForKey: NSLocaleCountryCode value: countryCode];
NSLog(#"countryName %#", countryName);
which works great, but I want to know how the countryName's will be displayed, so I can set up switch case's, which is hard if you dont know how exactly each country is spelt: USA, United States, United States of America, etc. Is there a list of countryCode from Apple, I cant find one.
Also is there a way to make sure the result is in English?
Apple uses the ISO-3166 standard.
"ISO standard ISO-3166" is accurate in most cases, but try selecting "Europe" as a region in iOS settings. You will get a return value of "150". Why "150"? Seems like a region code from here: http://en.wikipedia.org/wiki/UN_M.49. Or from here: http://site.icu-project.org/design/t/territory-region-apis
NSLocale gets its data from CFLocale which in turn gets its data from the
ICU - International Components for Unicode (Apple keep copies here). The file /icuSources/common/uloc.cpp contains almost all the information we usually see returned.
However, /cldrFiles/supplementalData.xml may be the primary source. This file comes from the CLDR - Unicode Common Locale Data Repository.
I have a need to convert NSString to double. If this string is in essence integer, then result is OK. If string is decimal, perhaps also with group separators then results are false. Any king of separator (whether "." or ",") whis is first in the string is always used as decimal separator.
I have tried to do something with NSScanner but I simply do not understand how to fix that problem.
Idea is following: whether I put in textfield integer, or decimal with or without group separator, I want to get proper decimal number.
I would be extremely glad to get any help.
Thanks in advance!
[string doubleValue] and a regular NSScanner always uses the . as the decimal separator. A localized NSScanner uses the decimal separator from the current locale. But both don’t know anything about grouping characters so they are inappropriate.
You have to use NSNumberFormatter to do this. Best to set it up in interface builder as #Gobra said. But you can also do this in code like this:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle: NSNumberFormatterDecimalStyle];
double value = [[formatter numberFromString: string] doubleValue];
If you need to know wether the string was valid or not you can check if the NSNumber object returned by numberFromString: is nil before you send it the doubleValue message.
Since you have mentioned text field I assume the problem is in binding some numeric value to the NSTextField. The proper way here is to use NSValueFormatter, there is a customizable formatter for numerics in the IB palette. Just drop it onto the text filed and set up the rules.
Even if the task have nothing to do with UI, you can still use [NSValueTransformer valueTransformerForName:aName] to create a transformed and convert the value with it.
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?
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.
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?
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.
I'm trying to convert a string of numbers, entered by the user, into a sexy string like Phone.app on the iPhone. Here is the code I'm using, which doesn't work (no special format comes out) and after a certain number of digits it just starts adding "0" to the end of the string.
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterNoStyle];
[formatter setPositiveFormat:#"+# (###) ###-###"];
[formatter setLenient:YES];
NSString *strDigits = [self stringByReplacingOccurrencesOfRegex:#"[^0-9+]" withString:#""];
return [formatter stringFromNumber:[NSNumber numberWithDouble:[strDigits doubleValue]]];
I think your issue is that NSNumberFormatter does not support brackets, spaces or dashes. I tried to implement the same method as you and it failed silently and just output unformatted text.
The general problem here is that the iPhone SDK doesn't provide a method to format phone numbers in a locale dependent way.
I have raised bugs with Apple for the following (two of these were duplicates of known issues so I've included Apple's original bug # for those):
#6933244 - Need iPhone SDK interface to format text as locale dependent phone number
#5847381 - UIControl does not support a setFormatter method
#6024985 - Overridden UITextField drawTextInRect method is never called
In an ideal world Apple would provide an NSPhoneNumberFormatter, and you would call setFormatter on your UIControl so it displayed text in a nice pretty way. Unfortunately that doesn't exist on the iPhone.
The UIPhoneFormats.plist contains predefined phone formats for each locale. So, if you're only interested in US phone numbers, you'll need to consider these formats:
+1 (###) ###-####
1 (###) ###-####
011 $
###-####
(###) ###-####
I had to do something similar, and I shared the results I got here:
http://the-lost-beauty.blogspot.com/2010/01/locale-sensitive-phone-number.html
Well a phone number should be 10 characters(11 with the leading 1), so you should start by changing this:
[formatter setPositiveFormat:#"+# (###) ###-####"];
And speaking of the leading 1, you need to check for that too.
Apple says you can implement your custom formatter if existing formatters' functionality is not enough:
NSFormatter is intended for subclassing. A custom formatter can restrict the input and enhance the display of data in novel ways. For example, you could have a custom formatter that ensures that serial numbers entered by a user conform to predefined formats. Before you decide to create a custom formatter, make sure that you cannot configure the public subclasses NSDateFormatter and NSNumberFormatter to satisfy your requirements.
For instructions on how to create your own custom formatter, see Creating a Custom Formatter.
See the section in Data Formatting Guide
One thing that is never mentioned here is that a NSNumberFormatter will always convert the value into, well, a NSNumber.
If you want a more generalized NSFormatter, subclass NSFormatter and implement the methods mentioned in the Creating a Custom Formatter.