Ошибка с валютой iPhone для формата евро с NSDecimalNumber с использованием NSLocale?

В моем приложении используются денежные значения, и я хотел бы представить эти значения в валюте и форматах, которые пользователь установил на своем iPhone, однако при тестировании у меня возникли проблемы с немецким форматом EURO.

У меня есть метод, который возвращает десятичное число (для хранения в основных данных) из строки в формате валюты. На самом деле строка была отформатирована другим (похожим) методом с использованием NSlocale.

Я протестировал локали для Великобритании, США, Японии и Германии, пока что только Германия вызвала какие-либо проблемы.

Вот код, передаваемая строка, например: 2,56 €

+ (NSDecimalNumber*)TLCurrencyFormatFromString:(NSString*)strNumber {


NSNumberFormatter *fmtrCurrencyFromStr = nil;

fmtrCurrencyFromStr = [[NSNumberFormatter alloc] init];
[fmtrCurrencyFromStr setFormatterBehavior:NSNumberFormatterBehavior10_4];
[fmtrCurrencyFromStr setLocale:[NSLocale currentLocale]];
[fmtrCurrencyFromStr setNumberStyle:NSNumberFormatterCurrencyStyle];
[fmtrCurrencyFromStr setGeneratesDecimalNumbers:YES];


NSLog(@"Currency Separator: %@", [fmtrCurrencyFromStr decimalSeparator]); //prints a comma
NSLog(@"Currency Code: %@", [fmtrCurrencyFromStr currencyCode]); //prints EUR

int currencyScale = [fmtrCurrencyFromStr maximumFractionDigits];

NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:currencyScale raiseOnExactness:FALSE raiseOnOverflow:TRUE raiseOnUnderflow:TRUE raiseOnDivideByZero:TRUE]; 

NSDecimalNumber* currencyNumber = [[NSDecimalNumber alloc] initWithDecimal:[[fmtrCurrencyFromStr numberFromString:strNumber] decimalValue]];

NSLog(@"Currency Number = %@", [currencyNumber decimalNumberByRoundingAccordingToBehavior:roundingBehavior]);

return [currencyNumber decimalNumberByRoundingAccordingToBehavior:roundingBehavior];

}

Переменная 'currencyNumber' печатается как: -18446912453607470532000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

тогда как во всех других локалях он будет печатать 2,56 для сохранения в Core Data как NSDecimalNumber.


person Glynton    schedule 21.11.2010    source источник


Ответы (3)


Установка свойства:

[fmtrCurrencyFromStr setLenient:YES];

Устраняет проблему для Франции, Германии, Норвегии, Великобритании, США, Японии, Намбии и т. д. Я не могу сказать, что это устраняет ее для всех, потому что я не тестировал все, но все те, которые я тестировал до сих пор. , это сработало.

person Glynton    schedule 30.11.2010

Я думаю, проблема в линии

NSDecimalNumber* currencyNumber = [[NSDecimalNumber alloc] initWithDecimal:[[fmtrCurrencyFromStr numberFromString:strNumber] decimalValue]];

Попробуйте заменить его на наиболее эквивалентную строку

NSDecimalNumber * currencyNumber = [fmtrCurrencyFromStr numberFromString:strNumber];

Вы установили generatesDecimalNumbers, так что они почти эквивалентны, за исключением одного раздражающего случая: nil.

Отправка сообщения в nil гарантированно ничего не сделает и вернет 0 для большинства стандартных типов (целых (за исключением 64-битных целых чисел в старых 32-битных средах выполнения), с плавающей запятой, типов указателей); он «возвращает» неинициализированную память, если метод возвращает структуру. NSDecimal — это структура.

(Основная причина, по сути, заключается в том, что среда выполнения не знает, насколько велика структура, поэтому не знает, сколько памяти нужно обнулить, поэтому вместо этого вы получаете «неинициализированную» память. что v не равно нулю.)

EDIT: Конечно, ваша другая проблема заключается в том, почему NSNumberFormatter неправильно анализирует цену. Это тяжело. Я бы попробовал убрать символ валюты.

person tc.    schedule 21.11.2010

Я убедился, что в iOS 4.3 использование флага [formatter setLenient:YES] работало у меня также и при использовании евро. Без установленного флага средство форматирования не возвращает правильные значения для евро.

person Ed Fernandez    schedule 28.10.2011