如何将本地化字符串数字转换为双精度数?

问题描述 投票:0回答:1

在我的代码中,我有一个用户通过文本字段设置的数字。

struct ContentView: View {
    @State private var numberText: String = ""
    
    var body: some View {
        TextField("0", text: $numberText)
    }
}

我喜欢将这个数字存储为双精度数。我知道以下方法:

// Option A
Double(numberText)

// Option B
try? Double(self, format: .number)

// Option C
(self as? NSString)?.doubleValue

// Option D
let formatStyle     = FloatingPointFormatStyle<Double>(locale: locale)
let parseStrategy   = FloatingPointParseStrategy(format: formatStyle, lenient: true)
let formatInput     = try? parseStrategy.parse(self)

// Option E
Manually parse by removing the locale.groupingSeparator and by replacing the locale.decimalSeparator with a '.' and then parse it with Double().

该问题出现在以下场景中。这些是我的设置:

  • 语言:英语
  • 地区:荷兰
  • 数字格式化器:1,234,567.89

选项 A、B 和 C 不起作用,因为它们不会考虑区域设置。他们总是会尝试解析带有点“23.45”的字符串。所以选项 D 最接近,但如果我给它当前的语言环境。它考虑了荷兰地区。这意味着它期望

23,45
而不是
23.45
。但是键盘使用数字格式化程序的设置,因此它将正确显示点作为小数分隔符。这意味着用户将输入
23.45
,解析器将产生错误的数字。

可能的答案

extension String {
    
    var doubleValue: Double? {
        var string = self.trimmingCharacters(in: .whitespacesAndNewlines)
        
        if let groupingSeparator = Locale.current.groupingSeparator {
            string = string.replacingOccurrences(of: groupingSeparator, with: "")
        }
        
        if let decimalSeparator = Locale.current.decimalSeparator, decimalSeparator != "." {
            string = string.replacingOccurrences(of: decimalSeparator, with: ".")
        }
        
        return Double(string)
    }
    
}
swift string double
1个回答
0
投票

新的

FormatStyle
API 似乎不支持设备的数字格式设置,而仅使用“区域”设置中设置的区域设置的默认值。

另一方面,旧的

NumberFormatter
确实正确地做到了这一点:

let formatter = NumberFormatter()
formatter.numberStyle = .decimal
// locale is Locale.current by default. You can optionally set this to the local from @Environment(\.locale)
// formatter.locale = ...
print(formatter.number(from: "1,6"))

您还可以直接将

NumberFormatter
传递给
TextField

TextField("Foo", value: $value, formatter: someFormatter)
© www.soinside.com 2019 - 2024. All rights reserved.