iOS get locale based description of number - ios

Not sure if this is possible, but for my app I would like to get a locale based string that describes a number.
For example, if I had the number 10,000,000.
In english, I would expect the phrase "Ten Million". However, in Hindi, it would be One crore. Is there any properties in NSNumberFormatter, or NSLocale that could help me with this?
I have checked the docs (NSNumberFormatter, NSLocale), and havent found what I'm looking for yet. Obviously I could write some code to handle these two cases, but I'd like a way that could work for any locale.
Edit: Thanks to leo for the answer! Here is a small snippet of code that will get anyone looking for the same thing started:
NSNumberFormatter formatter = [[NSNumberFormatter alloc] init];
[self.formatter setNumberStyle:NSNumberFormatterSpellOutStyle];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"hi_hi"];
[self.formatter setLocale:locale];
NSNumber * myNumber = [NSNumber numberWithInt:10000];
self.numberLabel.text = [self.formatter stringFromNumber:myNumber];

What you are looking for is the NSNumberFormatterSpellOutStyle style.
NSString* spelledOutString = [NSNumberFormatter localizedStringFromNumber:#10000000 numberStyle:NSNumberFormatterSpellOutStyle];

Related

iOS app with iTunes store - get currency code (not priceLocal)

We have an iOS app with in-app purchase and we want to track transactions with Google Analytics (enhanced ecommerce). We already have the proper handling for priceLocal, that's not the issue... we need to tell GA the specific currency code in use by the user. This info doesn't seems to be available directly and we would rather not do our own lookup.
Current code abstract:
// Set locale
NSLocale *storeLocale = product.priceLocale;
// instead of storeCountry we need storeCurrency, like USD, CAD, EUR, GBP...
NSString *storeCountry = (NSString *)CFLocaleGetValue((CFLocaleRef)storeLocale, kCFLocaleCountryCode);
[ecommerced setObject:storeCountry forKey:#"currencyCode"];
I haven't run this code to see if it works but this is how to get what you want.
NSNumberFormatter *formatter = [NSNumberFormatter new];
[formatter setNumberStyle: NSNumberFormatterCurrencyStyle];
[formatter setLocale: storeLocale];
NSLog("The currency code is: %#", formatter.currencyCode);
NSNumberFormatter Documentation

Word delimiter for given locale

How do I know if a language NSLocale uses spaces for delimiting words in a sentence (like English or other roman languages) or not (like Japanese)?
I expected to find this information under NSLocale Component Keys … no. Any idea? Do I really need to set my own dictionary for this. I'd appreciate any advice or related resource.
You can use NSLocal Components keys' NSLocaleExemplarCharacterSet to get the set of character in that language and then see if space is part of that language character set
NSLocale *jpLocale = [[NSLocal alloc] initWithLocalDentifier: #"ja_JP"];
NSCharacterSet *jpCharSet = (NSCharacterSet *)[jpLocale objectForKey: NSLocaleExemplarCharacterSet];
[jpCharSet characterIsMember: ' '] ? NSLog("Yeah it uses space"); : NSLog("Nope");
I still haven't found a great solution. As a workaround I am checking for spaces in fullStyle strings from a random date using the NSDateFormatter
NSDate* exampleDate = [NSDate dateWithTimeIntervalSince1970:0];
NSDateFormatter *dateFormatter = [NSDateFormatter new];
dateFormatter.locale = [NSLocale currentLocale];
dateFormatter.dateStyle = NSDateFormatterFullStyle;
NSString *testString = [dateFormatter stringFromDate:exampleDate];
BOOL localeLikelyUsesSpaceAsDelimitters = [testString rangeOfString:#" "].location == NSNotFound;
Better ideas?

NSNumberFormatter numberFromString decimal number

I'm trying to parse a NSString with a NSNumberFormatter like following.
NSNumberFormatter *myFormatter = [[[NSNumberFormatter alloc] init];
NSNumber *myNumber = [myFormatter numberFromString:#"42.00000"];
numberFromString returns a NSNumber object in the simulator but not on a device.
The decimals (.00000) are causing the return value to be nil on a device because parsing 42 (without the decimals) works just fine (both in the simulator and on a device).
The reason I'm using a NSNumberFormatter is because is like how it returns nil if the string is not a valid number (which is working against me here :p). NSString doubleValue does not provide this kind of behaviour. Also, NSDecimalNumber decimalNumberWithString doesn't do the job because [NSDecimalNumber decimalNumberWithString:#"4a2.00000"] returns 4.
Any ideas why this would not work on a device?
Is it the locale? I tried setting myFormatter.numberStyle = NSNumberFormatterNoStyle and NSNumberFormatterDecimalStyle but it changes nothing.
As #rmaddy already said in a comment, the decimal separator of NSNumberFormatter is
locale dependent. If you have a fixed input format with the dot as decimal separator,
you can set the "POSIX locale":
NSNumberFormatter *myFormatter = [[NSNumberFormatter alloc] init];
[myFormatter setLocale:[NSLocale localeWithLocaleIdentifier:#"en_US_POSIX"]];
NSNumber *myNumber = [myFormatter numberFromString:#"42.00000"];
Alternatively, you can use NSScanner to parse a double value, as e.g. described
here: parsing NSString to Double
42.00000 is not a string mate, why not #"42.00000"?

Converting double to string return strange value in objective c

I have an NSDictionary which consist of multiple key/pair values. One of them consist double value.
NSNumber *goalValue = [info objectForKey:#"goalValue"];
I put breakpoint and I found that goalValue store the normal value that I need.
and just below I convert it to NSSting like
NSString *stringValue=[goalValue stringValue];
and this stringValue store very strange value.
Guys please help me. I am totally puzzled, I did goggle but nothing change. Please help me. Thanks in advance.
The method stringValue will convert the NSNumber to string by internally calling descriptionWithLocale: with locale as nil and this method in turn will call initWithFormat:locale:,
From Apple docs,
To obtain the string representation, this method invokes NSString’s initWithFormat:locale: method, supplying the format based on the type the NSNumber object was created with:
So format specifier used for double is %0.16g(i.e. 16 digit precision) hence the value 98.09999999999999
I'd suggest using NSNumberFormatter,
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setMaximumFractionDigits:2]; //2 decimal places, change this as required.
NSString *string = [numberFormatter stringFromNumber:goalValue];
Hope that helps!
To prevent this behavior, I suggest using NSDecimalNumber (also this is from my experience best format when dealing with very precise amounts)
NSDecimalNumber *doubleDecimal = [[NSDecimalNumber alloc] initWithDouble:[info objectForKey:#"goalValue"]];
for two digits formatting, use numberFormatter
NSNumberFormatter * nf = [[NSNumberFormatter alloc] init];
[nf setMinimumFractionDigits:2];
[nf setMaximumFractionDigits:2];
NSString *stringValue = [nf stringFromNumber:doubleDecimal]
Its showing the rounded value so you can round the value to single digit using NSNumberFormatter.
NSNumberFormatter *fomatter = [[NSNumberFormatter alloc] init];
[fomatter setMaximumSignificantDigits:2];
NSString *stringValue=[fomatter stringFromNumber:goalValue];

ios: NSLocale/Grouping Separator - annoying warnings

I'm using NSLocale quite a lot for Numbers or Currency formatting. For example I use it this way:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
// Config the NSNumberFormatter ...
formatter.groupingSeparator = [[NSLocale currentLocale] objectForKey:NSLocaleGroupingSeparator];
The compiler always gives me the warning: Multiple methods named 'objectForKey:' found
This gets really annoying in larger projects (20+ warnings of this type). The only way I found to get rid of this warning is doing a type cast to NSDictionary:
formatter.groupingSeparator = [(NSDictionary *)[NSLocale currentLocale] objectForKey:NSLocaleGroupingSeparator];
This works but I'm not sure if this will lead to problems as [NSLocale currentLocale] seems not directly to be an NSDictionary ([[NSLocale currentLocale] class] returns __NSCFLocale).
Is there any better solution to this?
CMD+Click to your objectForKey statement. Xcode will find the method at NSDictionary.h.
Now change your code like
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
...
NSLocale *currentLocale = [NSLocale currentLocale];
formatter.groupingSeparator = [currentLocale objectForKey:NSLocaleGroupingSeparator];
and CMD+Click again to this objectForKey statement. Xcode will go to correct place, NSLocale.h.
Or, as you suggested, you can just force-cast NSLocale like
formatter.groupingSeparator = [(NSLocale *)[NSLocale currentLocale] objectForKey:NSLocaleGroupingSeparator];

Resources