【问题标题】:Second decimal place gets truncated if it is 0如果第二个小数位为 0,则会被截断
【发布时间】:2021-01-05 18:09:26
【问题描述】:

我是 Swift 新手,请耐心等待。 :)

我无法将输出货币显示到小数点后两位。目前,它只显示一位小数。例如,如果我输入 $1.10,则输出为 $1.1。

但是,如果我输入 $1.11,输出仍然是 $1.11。

func currencyInputDoubling() -> String {
    
    var number: NSNumber!
    let formatter = NumberFormatter()
    formatter.numberStyle = .currencyAccounting
    formatter.currencySymbol = CurrencyManager.shared.currentCurrency.sign
    formatter.maximumFractionDigits = 2
    formatter.minimumFractionDigits = 2
    
    var amountWithPrefix = self
    
    // remove from String: "$", ".", ","
    let regex = try! NSRegularExpression(pattern: "[^0-9]", options: .caseInsensitive)
    amountWithPrefix = regex.stringByReplacingMatches(in: amountWithPrefix, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, self.count), withTemplate: "")
    
    let double = (amountWithPrefix as NSString).doubleValue
    
    number = NSNumber(value: (double / 100))
    // if first number is 0 or all numbers were deleted
    guard number != 0 as NSNumber else {
        return ""
    }
    
    return "\(double / 100)"
}

【问题讨论】:

  • 你想用这个方法完成什么?
  • @JoakimDanielson - 这可能是为了实时格式化文本字段中的货币值。例如。用户键入“123456”,文本字段显示“$1,234.56”。如果用户继续输入,例如最后输入“7”,结果将是“$12,345.67”。这是格式化数据输入的常见模式。 (它显然忽略了文本位置问题,但却是一种常见的幼稚实现。)

标签: swift currency nsnumber numberformatter


【解决方案1】:

我建议使用 Locale 而不是 currencySymbol,并创建可重复使用的静态数字格式化程序。

let currencyFormatter: NumberFormatter = {
    let formatter = NumberFormatter()
    formatter.numberStyle = .currency
    formatter.locale = .current

    return formatter
}()

let numberFormatter: NumberFormatter = {
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    formatter.locale = .current
    formatter.minimumFractionDigits = 2
    formatter.maximumFractionDigits = 2

    return formatter
}()

然后方法可以简化为

func currencyInputDoubling(_ amountWithPrefix: String) -> String {
    guard let value = currencyFormatter.number(from: amountWithPrefix) else { return "" }

    return numberFormatter.string(from: value) ?? ""
}

如果您需要将 Locale 设置为 .current 以外的其他值,您可以将其作为参数传递

func currencyInputDoubling(_ amountWithPrefix: String, using locale: Locale) -> String {
    currencyFormatter.locale = locale
    numberFormatter.locale = locale
    guard let value = currencyFormatter.number(from: amountWithPrefix) else { return "" }

    return numberFormatter.string(from: value) ?? ""
}

【讨论】:

    【解决方案2】:

    我建议至少使用您创建的格式化程序,而不是进行字符串插值。当您使用简单的字符串插值返回 "\(double / 100)" 时,它无法利用格式化程序的小数位数设置。

    也许:

    func currencyInputDoubling() -> String {    
        let formatter = NumberFormatter()
        formatter.numberStyle = .currencyAccounting
        formatter.currencySymbol = CurrencyManager.shared.currentCurrency.sign
        formatter.maximumFractionDigits = 2
        formatter.minimumFractionDigits = 2
        
        // remove from String: "$", ".", ","
        let digitsOnly = filter("0123456789".contains)` // or, if you want to use regex, simply `let digitsOnly = replacingOccurrences(of: "[^0-9]", with: "", options: .regularExpression)`
    
        // return formatted string
        guard let value = Double(digitsOnly) {
            return ""
        }
    
        return formatter.string(for: value / 100) ?? ""
    }
    

    【讨论】:

      猜你喜欢
      • 2018-03-17
      • 1970-01-01
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      • 1970-01-01
      相关资源
      最近更新 更多