Swift 与 Objective-C

Swift 字符串长度:实测韩文、表情符号与字节

比较Character、Unicode scalar、UTF-16与UTF-8长度,验证等价韩文字典键,以及不会截断家庭表情符号的前缀截取。

3 分钟阅读
Swift 字符串长度:实测韩文、表情符号与字节 封面图

实现字符串限制前,先确定计数单位。Swift的count计算Character,也就是扩展字素簇;传输大小通常按字节计算。显示相同的字符,内部大小仍可能不同。

原理与设计判断

实验的韩文音节可以用一个预组合标量或三个组合字母标量表示。Swift String考虑规范等价性,字典查询也能使用等价键。家庭表情符号则展示多个标量组成一个Character。其他语言计算不同单位,本身不代表错误。 一手资料

复现代码

用Unicode escape固定精确输入,比较韩文两种形式的Character、标量和UTF-8数量。测量家庭表情符号的UTF-16与UTF-8长度,将它放在A与B之间,再用prefix和String.Index操作。空字符串另行测试。

这个独立示例已于 2026-10-23 使用 Apple Swift 6.4,以 Swift 6 语言模式在 arm64 macOS 目标环境运行。不需要网络或额外软件包。

下载完整 Swift 文件

请在下载文件的文件夹中运行。检查不通过时,precondition 会终止程序。请勿使用 -Ounchecked,因为它会移除这些检查。

swift -swift-version 6 swift-string-grapheme-cluster-indexing.swift
let composed = "\u{D55C}"
let decomposed = "\u{1112}\u{1161}\u{11AB}"
precondition(composed == decomposed)
precondition(composed.count == 1 && decomposed.count == 1)
precondition(composed.utf8.count == 3 && decomposed.utf8.count == 9)
precondition(decomposed.unicodeScalars.count == 3)
let lookup = [composed: 42]
precondition(lookup[decomposed] == 42)

let family = "\u{1F468}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}"
precondition(family.count == 1 && family.unicodeScalars.count == 7)
precondition(family.utf16.count == 11 && family.utf8.count == 25)
let text = "A" + family + "B"
precondition(text.count == 3 && String(text.prefix(2)) == "A" + family)
let second = text.index(after: text.startIndex)
precondition(String(text[second]) == family)
let empty = ""
precondition(empty.first == nil && empty.prefix(2).isEmpty)
print("hangul=characters:1,scalars:1/3,utf8:3/9 equal:true dictionary:42")
print("family=characters:1,scalars:7,utf16:11,utf8:25 prefix=2 empty=safe")

运行结果与解读

hangul=characters:1,scalars:1/3,utf8:3/9 equal:true dictionary:42
family=characters:1,scalars:7,utf16:11,utf8:25 prefix=2 empty=safe

两种韩文形式都是一个Character,但UTF-8分别为3与9字节,分解形式有三个标量。等价字典键可以查得42。家庭表情符号有一个Character、七个标量、十一个UTF-16单元、二十五个UTF-8字节。prefix(2)不会截断表情符号。

适用范围与限制

Character不保证完全符合所有语言中人对一个字的理解,还需考虑分割规则与Unicode版本。不能把韩文或表情符号一律算成每字三字节。Swift Dictionary也不总是需要显式NFC规范化,但外部系统的比较与编码契约须另行确认。

接下来要确认的事

先让服务器与客户端对字符数或UTF-8字节限制达成一致。预览可以使用prefix等Character API;频繁随机访问则比较数组转换成本与内存。缺失与空字符串的区别可接着看Optional实验。

延伸实验

来源与验证