提供String Extension自定义的 .decoded
方法:
var decoded: String {
guard let data = self.data(using: .utf8),
let decoded = String(data: data, encoding: .nonLossyASCII) else {
return self
}
return decoded
}
问题在于:
-
String(data: ..., encoding: .nonLossyASCII)
只能解析通过NSPropertyListSerialization
创建出来的 plist 风格字符串。 - 在 iOS 16+,
nonLossyASCII
对 Unicode 解码的支持变得不稳定,在 iOS 17/18 上经常会失败(尤其是非 plist 格式的字符串)。
✅ 正确做法(使用正则提取 + Unicode 转码)
我们可以手动解析 \uXXXX
并将其转换为字符:
extension String {
/// 手动将 \\uXXXX 转换为 Unicode 字符(兼容 iOS 所有版本)
var unicodeDecoded: String {
let pattern = #"\\u([0-9a-fA-F]{4})"#
let regex = try? NSRegularExpression(pattern: pattern, options: [])
let nsString = self as NSString
let results = regex?.matches(in: self, range: NSRange(location: 0, length: nsString.length)) ?? []
var decoded = self
for result in results.reversed() { // 从后往前替换避免位置错乱
if let range = Range(result.range(at: 1), in: self) {
let hex = String(self[range])
if let scalar = UInt32(hex, radix: 16),
let unicodeScalar = UnicodeScalar(scalar) {
decoded.replaceSubrange(Range(result.range, in: decoded)!, with: String(unicodeScalar))
}
}
}
return decoded
}
}
✅ 使用示例
let raw = "\\u60a8\\u597d\\uff0c\\u60a8\\u6240\\u63d0\\u95ee\\u7684\\u95ee\\u9898\\u6682\\u65f6\\u6ca1\\u6709\\u7b54\\u6848\\uff0c\\u8bf7\\u7a0d\\u540e\\u518d\\u8bd5\\u3002"
print(raw.unicodeDecoded)
🔚 输出:
您好,您所提问的问题暂时没有答案,请稍后再试。
💡总结
方法 | 状态 | iOS 18.4 |
---|---|---|
.nonLossyASCII |
❌ 不稳定/失效 | ❌ |
正则 + 手动 Unicode 解码 | ✅ 稳定可靠 | ✅ |