I am developing an application in which I wish to handle different currency formats, depending on the current locale. Using a NSNumberFormatter I can correctly translate a number into string and back without problems.
But, if I put the string value into a UITextField and later get it back, I won’t be able to convert the string back into a number and I will get a nil value instead.
Here is a sample code to explain the problem:
NSNumberFormatter *nf = [Utils currencyFormatter];
NSNumber *n = [NSNumber numberWithInt:10000];
NSString *s = [nf stringFromNumber:n];
NSLog(@"String value = %@", s);
UITextField *t = [[UITextField alloc] init];
// I put the string into the text field ...
t.text = s;
// ... and later I get the value back
s = t.text;
NSLog(@"Text field text = %@", s);
n = [nf numberFromString:s];
NSLog(@"Number value = %d", [n intValue]);
where the currencyFormatter method is defined this way:
+ (NSNumberFormatter *)currencyFormatter
{
static NSNumberFormatter *currencyFormatter;
if (!currencyFormatter) {
currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[currencyFormatter setLocale:[NSLocale currentLocale]];
if ([currencyFormatter generatesDecimalNumbers] || [[currencyFormatter roundingIncrement] floatValue] < 1) {
[currencyFormatter setGeneratesDecimalNumbers:YES];
[currencyFormatter setRoundingIncrement:[NSNumber numberWithFloat:0.01]];
}
}
return currencyFormatter;
}
(The inner if is used to force the formatter to always round to the smallest decimal digit, eg. even for CHF values).
What I get in the Console is this:
2012-03-29 00:35:38.490 myMutuo2[45396:fb03] String value = € 10.000,00
2012-03-29 00:35:38.494 myMutuo2[45396:fb03] Text field text = € 10.000,00
2012-03-29 00:35:38.497 myMutuo2[45396:fb03] Number value = 0
The strange part is that the spacing character between € and 1 in the first line is represented in the console through a mid-air dot, while in the second line this dot disappears. I believe this is an encoding-related problem.
Can anyone help me solve this problem?
Thank you!
Edit
I changed my test code to this:
NSNumberFormatter *nf = [Utils currencyFormatter];
NSNumber *n = [NSNumber numberWithInt:10000];
NSString *s = [nf stringFromNumber:n];
NSLog(@"String value = %@ (space code is %d)", s, [s characterAtIndex:1]);
UITextField *t = [[UITextField alloc] init];
t.text = s;
s = t.text;
NSLog(@"Text field text = %@ (space code is %d)", s, [s characterAtIndex:1]);
n = [nf numberFromString:s];
NSLog(@"Number value = %d", [n intValue]);
to discover this:
2012-03-29 02:29:43.402 myMutuo2[45993:fb03] String value = € 10.000,00 (space code is 160)
2012-03-29 02:29:43.405 myMutuo2[45993:fb03] Text field text = € 10.000,00 (space code is 32)
2012-03-29 02:29:43.409 myMutuo2[45993:fb03] Number value = 0
The NSNumberFormatter writes down the space as a non-breaking space (ASCII char 160), and then the UITextField re-encodes that space as a simple space (ASCII char 32). Any known workaround for this behaviour? Perhaps I could just make a replacement of the space with a non-breaking space but … will it work for all the locales?
I was able to solve this problem only extending the
UITextFieldthrough a custom class. In this new class I put a new@propertyof typeNSStringin which I store the “computed” string value for the text field. This string will never be modified and will preserve the original encoding of the content of the text field.When you need to work again on the original untouched content of the text field you have to refer to this new property instead of referring to the
textproperty.Using a separate string container is the only way to avoid these strange encoding changes.