【问题标题】:Wrong behaviour on formatting decimal格式化小数的错误行为
【发布时间】:2021-12-23 19:17:13
【问题描述】:

我想用格式化字符串(货币)实现 TextField

我使用 Binding 将输入的字符串格式化为十进制并在 TextField 格式化字符串中显示:

问题:在输入第 4 个或很少输入第 5 个数字后,字符串跳到 0。

来自 Playground 的代码,显示了所有内容:

import Foundation

let formatter = NumberFormatter()
formatter.locale = Locale(identifier: "sk-SK")//locale
formatter.numberStyle = .currency
formatter.currencySymbol = ""

var formattedValue = formatter.string(for: 1) ?? .init("")
var number = formatter.number(from: "1")?.decimalValue ?? 0

formattedValue = formatter.string(for: 10) ?? .init("")
number = formatter.number(from: "10")?.decimalValue ?? 0

formattedValue = formatter.string(for: 100) ?? .init("")
number = formatter.number(from: "100")?.decimalValue ?? 0

formattedValue = formatter.string(for: 1000) ?? .init("")
number = formatter.number(from: "1 000")?.decimalValue ?? 0 // Problem here. "1 000" -> 0

number = formatter.number(from:newValue.replacingOccurrences(of: " ", with: ""))?.decimalValue ?? 0 // Works in Playground, but it doesn't help in real code (trying to localize this problem now)


formattedValue = formatter.string(for: 1) ?? .init("")
number = formatter.number(from: formattedValue!)?.decimalValue ?? 0

formattedValue = formatter.string(for: 10) ?? .init("")
number = formatter.number(from: formattedValue!)?.decimalValue ?? 0

formattedValue = formatter.string(for: 100) ?? .init("")
number = formatter.number(from: formattedValue!)?.decimalValue ?? 0

formattedValue = formatter.string(for: 1000) ?? .init("")
number = formatter.number(from: formattedValue!)?.decimalValue ?? 0 // But here despite of same looking formattedValue ("1 000") formatter convert string correct.

【问题讨论】:

  • 如果您发布Minimal, Reproducible Example,您可能会获得更多帮助。
  • 谢谢!我本地化了问题并从 Playground 中添加了列表
  • "1 000" 不是一个将返回十进制值 1000 的字符串。失败,并且该行的那部分返回 nil。由于您提供了备用默认值 0,这就是您所得到的。如果您希望您的字符串有空格,则需要先将其删除,然后再尝试将它们转换为小数。话虽如此,提供的答案为您提供了一种很好的干净方式,尽管在尝试转换之前需要进行一些检查以确保字符串实际上是一个数字。

标签: swift swiftui binding number-formatting


【解决方案1】:

好吧,我会实现一个扩展,在键盘关闭后更新文本。可能不是最好或“最干净”的答案......但我喜欢在 swiftui 上使用扩展。

注意:下次提供可重现的代码。

extension String{
func format(string: String) -> String{
    guard let amount = Double(string) else{
        return string
    }
    let formatter = NumberFormatter()
    formatter.locale = Locale.current // Change this to another locale if you want to force a specific locale, otherwise this is redundant as the current locale is the default already
    formatter.numberStyle = .currency
    if let formattedTipAmount = formatter.string(from: amount as NSNumber) {
        return formattedTipAmount
    }
    return string
}}

然后在您的 TextField 中像这样使用它,如果这不是您想要的,那么只需编辑扩展以提供您想要的结果。

TextField("text",text: $amount, onEditingChanged: { (editingChanged) in
            if !editingChanged {
                print("Editing...")
                amount = "".format(string: amount)
            }
        })
            .keyboardType(.decimalPad)

【讨论】:

  • 谢谢!我本地化了问题并从 Playground 中添加了列表
猜你喜欢
  • 2018-08-31
  • 2014-08-09
  • 2015-02-21
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
相关资源
最近更新 更多