为什么Swift的NumberFormatter处理货币格式时需非断空格才能正常解析?
核心原因
这个行为是NumberFormatter的设计机制和区域格式规范共同决定的:
- 首先,
pt_BRlocale对应的Unicode区域货币格式标准中,明确规定货币符号R$和数值之间的分隔符为非断空格(\u{00a0}),而非普通空格。使用.currency样式的NumberFormatter默认会严格遵循对应locale的格式规范进行解析,对分隔符的类型是强校验的,不匹配就会返回nil。 - 你通过
string(from:)生成的格式化字符串是完全符合locale规范的,所以可以正常反向解析;而你手动构造/输入掩码生成的字符串用了普通空格,不符合格式要求,因此解析失败。
更稳妥的解决方案
除了手动替换空格之外,更推荐开启NumberFormatter的宽松解析模式,它会自动兼容常见的格式差异(包括普通空格和非断空格的区别):
var currencyFormatter: NumberFormatter { let formatter = NumberFormatter() formatter.locale = Locale(identifier: "pt_BR") formatter.numberStyle = .currency formatter.maximumFractionDigits = 2 // 开启宽松解析,兼容非标准格式输入 formatter.isLenient = true return formatter }
开启后直接传入带普通空格的R$ 1.700,00也能正常解析出1700.00,不需要额外做字符串替换。如果希望从根源避免问题,可以修改你的UITextField输入掩码逻辑,在拼接货币符号和数值时直接使用非断空格\u{00a0},和系统格式化器的输出规范保持一致。
内容的提问来源于stack exchange,提问作者Cayoda
相关产品推荐
相关产品推荐

