20

似乎 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 方法产生的内容完全匹配。

在设置应用程序中将 Region Format 设置为 France,然后在以下代码中将 currencyNumber 设置为 12.34,导致 currencyString 设置为 '12,34 €' :

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

显然,专门针对欧元解决这个问题相当容易,但我希望在尽可能多的国家销售这个应用程序,我认为其他地区肯定会发生类似的情况。

有人有答案吗?

TIA,邓肯

4

7 回答 7

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,一个不间断的空格,而不是预期的,

OS X / iOS 上的格式化程序类(以及正则表达式类等)利用ICU 库,其他项目也使用。我发现了至少两个关于这个特定问题的其他错误报告。不过,这似乎是预期的行为。(我花了一些时间筛选 ICU 的源代码以找到它的定义,但它是一个迷宫。)

我的建议暂时是传递-setLenient:YES给货币格式化程序。甚至可能向 Apple 的雷达提交错误报告。

于 2010-10-10T03:35:17.923 回答
2

您是否尝试在设置中将区域设置为法国,然后尝试获取字符串的数字量?或者您可以手动设置数字格式化程序的本地setLocale:。NSNumberFormatter 使用它所必须的任何语言环境来确定数字是什么字符串。如果您只需要用户能够为其区域输入本地化货币字符串,请将系统更改为该区域设置,然后进行测试。如果您需要用户能够输入多种格式,请添加某种选择系统,以便您知道他们输入的内容。

于 2010-08-25T21:16:47.753 回答
2

我用欧元验证了(至少在 iOS 4.3 上)使用 [formatter setLenient:YES] 标志对我有用。如果没有设置该标志,格式化程序不会返回正确的欧元值。

于 2011-10-28T08:19:45.280 回答
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"

格式化的值也将与相应的货币符号一起返回。

于 2017-12-04T08:59:21.880 回答
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

于 2011-05-05T18:58:59.243 回答
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变量将为 nil。要获得所需的结果,请在字符串的两个位置使用不间断空格(作为千位分隔符和货币符号分隔符):

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

然后转换将按预期发生。

当然,如果您希望使用宽松的转换,那么这是最简单的方法,它可能是处理人工输入的最佳选择。

另一方面,在处理机器生成的数据时,可能不希望对字符串进行宽松的解释,因为您将失去检查输入数据正确性的能力。

于 2013-05-13T16:50:30.207 回答
0

在 Swift 中执行此操作的方法是:

   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 是输入的数字。

于 2014-10-26T01:18:13.553 回答