Swift新版本中UnicodeScalars初始化报错,如何从Unicode获取字符?
问题解答:Swift中通过Unicode编码生成字符及TS代码转Swift
一、UnicodeScalar初始化报错的原因及解决
底层变化
Swift 5及以后版本中,UnicodeScalar针对UInt16和UInt32的初始化器改为可失败初始化器(返回Optional<UnicodeScalar>),核心原因是:
- 并非所有
UInt16/UInt32值都是有效的Unicode标量,比如UInt16的代理对范围(0xD800-0xDFFF)、UInt32超出0x0000-0x10FFFF的数值均无效。 - Swift为强化类型安全,要求开发者显式处理无效值场景,不再提供非可选的初始化器。
修复后的代码
若确定编码值为有效Unicode标量,可直接强制解包;不确定则用可选绑定处理:
let value0: UInt8 = 0x61 let value1: UInt16 = 0x5927 let value2: UInt32 = 0x1F34E // UInt8的初始化器仍为非可选(0-255均为有效单字节标量) let string0 = String(UnicodeScalar(value0)) // "a" // UInt16/UInt32需处理可选值 if let scalar1 = UnicodeScalar(value1) { let string1 = String(scalar1) // "大" } if let scalar2 = UnicodeScalar(value2) { let string2 = String(scalar2) // "🍎" } // 确定值有效时,也可直接强制解包 let string1Force = String(UnicodeScalar(value1)!) let string2Force = String(UnicodeScalar(value2)!)
二、TypeScript代码转Swift
原TS代码逻辑:从字符串末尾开始,每次截取2个字符解析为十六进制Unicode编码,转成字符后拼接到结果头部。
转换后的Swift代码
func convertHexStringToUnicode(_ str: String) -> String { var result = "" var currentIndex = str.count let charArray = Array(str) while currentIndex >= 2 { let start = currentIndex - 2 let hexSubstring = String(charArray[start..<currentIndex]) if let unicodeValue = UInt32(hexSubstring, radix: 16), let scalar = UnicodeScalar(unicodeValue) { result = String(scalar) + result } currentIndex -= 2 } // 处理字符串长度为奇数的情况 if currentIndex == 1 { let hexSubstring = String(charArray[0]) if let unicodeValue = UInt32(hexSubstring, radix: 16), let scalar = UnicodeScalar(unicodeValue) { result = String(scalar) + result } } return result } // 使用示例 let testStr = "6159271F34E" print(convertHexStringToUnicode(testStr)) // 输出:"a大🍎"
代码说明
- Swift的
String基于字符而非字节存储,无法直接用整数索引访问,因此先转为[Character]数组方便截取。 - 使用
UInt32解析十六进制值,因为Unicode标量最大范围为0x10FFFF,超出UInt16的上限(0xFFFF)。 - 补充了奇数长度字符串的处理逻辑,与原TS代码的
i >=1逻辑对齐。
内容的提问来源于stack exchange,提问作者Sebastian
相关产品推荐
相关产品推荐

