NumberFormatter 和货币字符串的欧元错误

Euro errors with NumberFormatter and Currency Strings

我在 Swift(字符串扩展)中编写了一个函数来获取任何货币字符串,例如“$500.00”或“250,75 €”,甚至是“500”,然后 return来自它的 nsdecimalnumber。

不幸的是,当我传入“250,75 €”时,它命中了我代码的 if (nf.number(from: self) == nil) 部分并评估为 nil,因此 return什么都没有。它似乎只在您用逗号添加更改时发生,例如 250,75。但是,如果我做了 250,它就会起作用。它似乎只为欧元这样做。美元运作良好($500.00、125.75 等)

这是我的代码。有什么想法吗?感谢您的宝贵时间!

extension String{
func toDecimalFromCurrencyString() -> NSDecimalNumber
    {

        let nf = NumberFormatter()
        nf.numberStyle = NumberFormatter.Style.currency
        nf.formatterBehavior = NumberFormatter.Behavior.behavior10_4
        nf.generatesDecimalNumbers = true

        var test = self.replacingOccurrences(of: nf.currencySymbol!, with: "", options: NSString.CompareOptions.literal, range: nil)
        test = test.replacingOccurrences(of: nf.currencyDecimalSeparator!, with: "", options: NSString.CompareOptions.literal, range: nil)
        test = test.replacingOccurrences(of: nf.currencyGroupingSeparator!, with: "", options: NSString.CompareOptions.literal, range: nil)
        let scanner: Scanner = Scanner(string:test)
        let isNumeric = (scanner.scanDecimal(nil) && scanner.isAtEnd)

        //If the string entered isn't numeric (for example ... or $$$, then fail)
        if (self.trimmingCharacters(in: CharacterSet.whitespaces).utf16.count == 0 || (!isNumeric))
        {
            return 0.0
        }
        //If the string contains more than one decimal separator (.), or more than one currency symbol ($), return 0.0
        else if ((self.components(separatedBy: nf.currencyDecimalSeparator!).count-1) > 1 || (self.components(separatedBy: nf.currencySymbol!).count - 1) > 1) {
            return 0.0
        }
        //If the string contains more than one consecutive currency grouping separator (i.e. ,,) then return 0.0
        else if ((components(separatedBy: nf.currencyGroupingSeparator! + nf.currencyGroupingSeparator!).count-1) > 0)
        {
            return 0.0
        }
        else
        {
            if (nf.number(from: self) == nil) {
                return 0.00
            }
            else {
                return nf.number(from: self) as! NSDecimalNumber
            }
        }
    }


}

您可以简单地 trim 字符串中的所有非数字并使用两个数字格式化程序,一个带点,另一个带逗号,并在链中使用 nil 合并运算符,如下所示:

extension Formatter {
    static let decimalWithDotSeparator: NumberFormatter = {
        let numberFormatter = NumberFormatter()
        numberFormatter.numberStyle = .decimal
        numberFormatter.decimalSeparator = "."
        return numberFormatter
    }()
    static let decimalWithCommaSeparator: NumberFormatter = {
        let numberFormatter = NumberFormatter()
        numberFormatter.numberStyle = .decimal
        numberFormatter.decimalSeparator = ","
        return numberFormatter
    }()
}

extension String {
    var numberFromCurrency: NSDecimalNumber? {
        var string = self
        while let first = string.characters.first, Int("\(first)") == nil {
            string = String(string.characters.dropFirst())
        }
        while let last = string.characters.last, Int("\(last)") == nil {
            string = String(string.characters.dropLast())
        }
        return (Formatter.decimalWithDotSeparator.number(from: string) ??
                Formatter.decimalWithCommaSeparator.number(from: string) ?? 0)
                .decimalValue.decimalNumber
    }
}

extension Decimal {
    var decimalNumber: NSDecimalNumber { return NSDecimalNumber(decimal: self) }
}

let dollar = "9.99"
dollar.numberFromCurrency   // 249.99

let real = "R9,99"
real.numberFromCurrency   // 249.99

let euro = "0,50€"
euro.numberFromCurrency    // 0.5