为何se_SV区域下CurrencyFormatter生成的字符串与手动字符串不相等?
为什么两个看似相同的字符串判断不相等?
这大概率是因为不可见的特殊字符差异,具体到瑞典语(se_SV)区域的货币格式化场景,最常见的问题出在这一点:
- 千分位分隔符的类型:
currencyFormatter生成的字符串里,千分位用的是非-breaking空格(Unicode编码U+00A0),而你手动输入的是普通空格(U+0020)。这两个字符肉眼看起来完全一样,但计算机识别它们是不同的字符,直接用==判断自然会返回false。
举个具体的代码示例:
let formatter = NumberFormatter() formatter.locale = Locale(identifier: "se_SV") formatter.numberStyle = .currency let firstString = formatter.string(from: 1234.56) ?? "" // firstString实际内容是 "1 234,56 kr" (注意:这里的空格是U+00A0) let secondString = "1 234,56 kr" // 这里的空格是普通空格U+0020
怎么验证这个差异?
你可以把两个字符串转成Unicode标量值来直观查看:
print(firstString.unicodeScalars.map { $0.value }) print(secondString.unicodeScalars.map { $0.value })
对比输出结果,你会发现对应空格位置的数值一个是160(U+00A0),一个是32(U+0020),这就是判断不相等的核心原因。
怎么解决这个问题?
如果需要让两个字符串能正确匹配,有两种常用方式:
- 手动替换特殊空格:把格式化后的字符串里的非-breaking空格替换成普通空格
let normalizedFirstString = firstString.replacingOccurrences(of: "\u{00A0}", with: " ") if normalizedFirstString == secondString { // 此时会返回true } - 使用Unicode规范化方法:将字符串转为兼容的规范化形式
let normalizedFirst = firstString.precomposedStringWithCanonicalMapping let normalizedSecond = secondString.precomposedStringWithCanonicalMapping if normalizedFirst == normalizedSecond { // 也能正确匹配 }
另外补充一点:本地化场景下的字符串比较经常会遇到这类“肉眼不可见”的字符差异,比如不同语言的空格、连字符、引号等,直接用==判断前最好先做规范化处理哦。
内容的提问来源于stack exchange,提问作者Oleg Gordiichuk
相关产品推荐
相关产品推荐

