一般来说,Swift对于将字形集群计为单个字符非常非常聪明。例如,如果我想制作黎巴嫩旗帜,我可以合并两个Unicode字符
正如预期的那样,这是Swift中的一个角色:
let s = "\u{1f1f1}\u{1f1e7}"
assert(s.characters.count == 1)
assert(s.utf16.count == 4)
assert(s.utf8.count == 8)
但是,假设我想制作Fitzpatrick Type-5的自行车表情符号。如果我结合
Swift将此组合计为两个字符!
let s = "\u{1f6b4}\u{1f3fe}"
assert(s.characters.count == 2) // <----- WHY?
assert(s.utf16.count == 4)
assert(s.utf8.count == 8)
为什么这两个字符而不是一个?
为了说明我期望它为1的原因,请注意该群集实际上被解释为有效的表情符号:
答案 0 :(得分:7)
部分答案在emrys57的评论中提到的bug report中给出。将Unicode字符串拆分为“字符”时,Swift显然使用UAX #29 Unicode Text Segmentation中定义的字形集群边界。有rule not to break between regional indicator symbols,但表情符号修饰符没有这样的规则。因此,根据UAX#29,字符串"\u{1f6b4}\u{1f3fe}"
包含两个字形集群。有关解释,请参阅Unicode邮件列表中Ken Whistler的this message:
这是因为修饰符的回退行为是 简单地说是独立的象形文字,即颜色样本图像。 [...]你需要额外的,具体的 关于这些序列的知识 - 它不仅仅是从a 默认实现字形集群的UAX#29规则。