NSLocaleを使用したNSDecimalNumberのユーロ形式のiPhone通貨のバグ?
-
26-09-2019 - |
質問
私のアプリは通貨値を使用しており、これらの値をユーザーが iPhone に設定した通貨と形式で表したいのですが、テスト中にドイツのユーロ形式で問題が発生したようです。
通貨形式の文字列から(コアデータに保存するための)10進数を返すメソッドがあります。この文字列は、実際には 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」変数は次のように出力されます。-18446912453607470532000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0
一方、他のすべてのロケールでは、NSDecimalNumber としてコア データに保存するために 2.56 が出力されます。
解決
プロパティを設定します:
[fmtrCurrencyFromStr setLenient:YES];
修正フランス、ドイツ、ノルウェー、英国、米国、日本、Nambiaなどのための問題...私はしかし、すべての人の私がしたので、私はすべてをテストしていないので、それはすべてのためにそれを修正したと言うことはできませんこれまでにテストし、それが働いています。
他のヒント
私 考える あなたの問題は回線にあります
NSDecimalNumber* currencyNumber = [[NSDecimalNumber alloc] initWithDecimal:[[fmtrCurrencyFromStr numberFromString:strNumber] decimalValue]];
ほぼ同等の行に置き換えてみてください
NSDecimalNumber * currencyNumber = [fmtrCurrencyFromStr numberFromString:strNumber];
設定しました generatesDecimalNumbers
, したがって、この 2 つは、1 つの厄介なケースを除いてほぼ同等です。なし。
nil にメッセージを送信すると、ほとんどの標準型 (整数 (古い 32 ビット ランタイムの 64 ビット整数を除く)、浮動小数点、ポインター型) では何もせず 0 が返されることが保証されています。メソッドが構造体を返す場合、初期化されていないメモリを「返します」。NSDecimal は構造体です。
(根本的な理由は、ランタイムが構造体の大きさを知らないため、どれだけのメモリをゼロにするかが分からないため、代わりに「初期化されていない」メモリが得られることです。やるときはたいていこれを打ちます v.frame
v が nil でないことを保証せずに。)
編集: もちろんあなた 他の 問題は、NSNumberFormatter が価格を正しく解析しない理由です。それは難しいですね。通貨記号を削除してみます。
私はiOSの4.3に[フォーマッタsetLenient:YES]を使用していることが確認フラグをうまくユーロを使用して私のために働きました。そのフラグを設定せずに、フォーマッタはユーロに対して正しい値を返しません。