2010-08-24 59 views
20

似乎NSNumberFormatter無法將歐元(也可能是其他)貨幣字符串解析爲數字類型。有人可以證明我錯了。使用NSNumberFormatter從國際貨幣字符串中獲取十進制值

我試圖使用以下方法來從貨幣字符串得到一個數字量:

NSNumberFormatter *currencyFormatter = [[[NSNumberFormatter alloc] init] autorelease]; 
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; 
NSNumber *currencyNumber = [currencyFormatter numberFromString:currencyString]; 

這工作得很好英國和美國的貨幣金額。它甚至可以處理$和£以及數千個分隔符,而且沒有問題。

但是,當我使用歐元貨幣數量(在設置應用程序中將區域格式設置爲法國或德國)時,它將返回一個空字符串。以下所有字符串失敗:

12,34 € 
12,34 
12.345,67 € 
12.345,67 

值得一提的是,這些字符串使用相應的語言環境時,正是出來的NSNumberFormatter的stringFromNumber方法的匹配。

地區格式設置到法國在設置應用程序,然後在下面的代碼中設置currencyNumber至12.34,在的currencyString結果被設置爲'12,34€」:

NSNumberFormatter *currencyFormatter = [[[NSNumberFormatter alloc] init] autorelease]; 
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; 
NSString *currencyString = [currencyFormatter stringFromNumber:currencyNumber]; 

這顯然是相當這個問題很容易針對歐元進行解決,但我希望能夠在儘可能多的國家銷售這個應用程序,而且我認爲類似的情況一定會發生在其他地區。

有沒有人有答案?

TIA,鄧肯

+0

我還沒有找到解決方案,所以任何輸入都將不勝感激。謝謝,鄧肯 – pieSquared 2010-09-15 10:25:22

+0

我會建議提交一份錯誤報告。 – 2011-05-06 07:19:54

回答

20

這是一個困難的問題。做了以下工作沒有問題:

double moneyAmount = 1256.34; 
NSLocale *french = [[NSLocale alloc] initWithLocaleIdentifier:@"fr_FR"]; 
NSNumberFormatter *currencyStyle = [[NSNumberFormatter alloc] init]; 

[currencyStyle setLocale:french]; 
[currencyStyle setNumberStyle:NSNumberFormatterCurrencyStyle]; 
NSNumber *amount = [NSNumber numberWithDouble:moneyAmount]; 
NSString *amountString = [currencyStyle stringFromNumber:amount]; 

NSNumber *pAmount = [currencyStyle numberFromString:amountString]; // == 1256.34 

然而,-currencyGroupingSeparator方法的輸出返回字符串\u00a0,一個non-breaking space,而不是預期的,

OS X/iOS上的格式化程序類(以及正則表達式類等)使用ICU library,也被其他項目使用。我發現至少有two其他bug關於這個特定問題的報告。看起來,這是expected行爲,但。 (我花了一些時間通過ICU來源篩選,以找到它的定義,但它是一個迷宮。)

我的建議,暫時,將通過-setLenient:YES貨幣格式化。也許甚至可以用Apple的雷達報告錯誤報告。

+2

'setLenient:'是黃金。 – 2011-04-05 19:28:11

2

您是否嘗試過在設置區域設定到法國,然後試圖獲得該字符串的數字量?或者你可以用setLocale:手動設置數字格式化器的本地。 NSNumberFormatter使用它所具有的任何區域設置來確定數字是一個字符串。如果您只需要用戶能夠爲其所在區域輸入本地貨幣字符串,請將系統更改爲該區域設置,然後進行測試。如果你需要用戶能夠輸入多種格式,然後添加某種選擇系統,以便知道他們正在投入什麼。

+0

是的,一切都在正確的語言環境下完成。我不需要支持多種貨幣,只需使用用戶本地語言環境中的字符串即可。因此,在上面的示例中,語言環境設置爲法國(或德國等)。我會更新這個問題;) – pieSquared 2010-08-26 07:22:00

1

我有使用難看答案NSScanner

NSArray * testStrings = [NSArray arrayWithObjects:@"12,34 €", @"12,34" ,@"12.345,67 €" ,@"12.345,67", nil]; 

    NSCharacterSet * charset = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; 

    for(NSString * s in testStrings) 
    { 
     s = [s stringByReplacingOccurrencesOfString:@"." withString:@""]; 
     s = [s stringByReplacingOccurrencesOfString:@"," withString:@"."]; 
     NSScanner * scanner = [NSScanner scannerWithString:s]; 
     [scanner setCharactersToBeSkipped:charset]; 
     float f; 
     [scanner scanFloat:&f]; 
     NSLog(@"float output is %.2f",f); 
    } 

輸出:
2011-05-05 12:56:25.460 ScannerTest [10882:903]浮動輸出是12.34
2011-05-05 12 :56:25.473 ScannerTest [10882:903]浮點輸出是12.34
2011-05-05 12:56:25.474 ScannerTest [10882:903]浮點輸出是12345.67
2011-05-05 12:56:25.475 ScannerTest [ 10882:903]浮點輸出爲12345.67

+0

很棒,爲我工作。保存我的時間:) – Dhaval 2013-02-14 09:32:30

2

我驗證了(至少在iOS 4.3上)使用[formatter setLenient:YES]標誌爲我使用歐元。沒有設置該標誌,格式化程序不會爲歐元返回正確的值。

0

使用默認設置(lenient = NO),那麼如果他們完全一樣格式化數字到字符串時,它產生的字符串格式化只會將字符串轉換爲數字。

因此,如果您想要使用非寬鬆轉換,您應該知道在許多語言環境中(全部?),這意味着輸入字符串中的空格必須是不分開的(\u00a0)。即:

NSString *amount = @"10 000,00 €"; 

NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; 
formatter.numberStyle = NSNumberFormatterCurrencyStyle; 

formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier: @"fr_FR"]; 

NSNumber *number = [currencyFormatter numberFromString: amount]; 

這不會產生預期的結果,因爲number變量將是零。要獲得期望的結果,使用非打破空間中的字符串的兩個地方(如千位分隔符和貨幣符號分隔符):

amount = @"10\u00a0000,00\u00a0€"; 

如預期那麼會發生轉換。

當然,如果你想使用寬鬆轉換,然後就是去最簡單的方法,它可能將是人類處理輸入的最佳選擇。

在另一方面,處理機器生成的數據時,琴絃的寬鬆解釋可能不是可取的,因爲你將失去檢查輸入數據的正確性的能力。

0

在斯威夫特做到這一點的方法是:

var locale = NSLocale.currentLocale() 
    var formatter = NSNumberFormatter() 
    formatter.locale = NSLocale(localeIdentifier: "en_US") 
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle 

    var moneyDouble = formatter.numberFromString(textField.text)?.doubleValue 

假設的TextField.text是所輸入的號碼。

2

其在Swift中的工作代碼

let formatter = NumberFormatter() 
    formatter.usesGroupingSeparator = true 
    formatter.locale = Locale(identifier: "de_DE") 
    formatter.numberStyle = NumberFormatter.Style.currency 
    formatter.string(from: NSNumber(floatLiteral: InputAsDoubleValue))! 

標識符:

  • 德國 - "de_DE"
  • 美國 - "en_US"
  • 法國 - "fr_FR"

格式化的值也將返回各自的貨幣符號。