You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中NumberFormatter格式化货币TextField输入4位数值跳0问题

问题成因
  1. 千位分隔符字符不匹配:sk-SK地区的货币格式化使用**非断空格(Unicode编码U+00A0)**作为千位分隔符,和普通ASCII空格(U+0020)肉眼显示完全一致但编码不同。你手动输入的"1 000"用的是普通空格,NumberFormatter无法将其识别为合法的千位分隔符,解析失败返回nil,最终走兜底逻辑得到0。你在Playground里替换普通空格可生效,是因为手动构造的字符串用的是普通空格,真实运行时formatter生成的分隔符是非断空格,仅替换普通空格的逻辑无法处理,所以会失效。
  2. 解析规则过于严格:.currency类型的NumberFormatter默认开启严格解析,要求输入字符串完全匹配当前地区的货币格式,缺少小数位、分隔符不匹配等小问题都会导致解析失败。
修复方案

1. 调整NumberFormatter配置

首先放宽解析规则,减少不必要的解析失败:

let formatter = NumberFormatter()
formatter.locale = Locale(identifier: "sk-SK")
formatter.numberStyle = .currency
formatter.currencySymbol = ""
// 新增配置
formatter.isLenient = true // 开启宽松解析,兼容部分格式不匹配的输入
formatter.generatesDecimalNumbers = true // 直接生成Decimal类型,避免NSNumber转Decimal的精度损失

2. 统一清洗输入字符串

不要只替换普通空格,兼容所有类型的千位分隔符:

// 方案1:直接移除所有空白字符,适配所有空格类型的千位分隔符
let cleanedInput = newValue.components(separatedBy: .whitespaces).joined()
// 方案2:针对性移除当前地区的千位分隔符,兼容性更强
if let groupingSeparator = formatter.groupingSeparator {
    cleanedInput = newValue.replacingOccurrences(of: groupingSeparator, with: "")
}
let number = formatter.number(from: cleanedInput)?.decimalValue ?? 0

3. 双向绑定逻辑适配

处理TextField的绑定逻辑,避免输入过程中格式跳变:

@State private var amount: Decimal = 0

var formattedAmount: Binding<String> {
    Binding(
        get: {
            formatter.string(for: amount) ?? ""
        },
        set: { newValue in
            let cleaned = newValue.components(separatedBy: .whitespaces).joined()
            amount = formatter.number(from: cleaned)?.decimalValue ?? 0
        }
    )
}

// 调用示例
TextField("请输入金额", text: formattedAmount)
    .keyboardType(.decimalPad)

内容的提问来源于stack exchange,提问作者Konstantin.Efimenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 19:15:06