一尘不染

当count标志表情符号出现时,Swift countElements()返回不正确的值

swift

let str1 = “🇩🇪🇩🇪🇩🇪🇩🇪🇩🇪”
let str2 = “🇩🇪.🇩🇪.🇩🇪.🇩🇪.🇩🇪.”

println("\(countElements(str1)), \(countElements(str2))")

结果:1、10

但是str1不应该有5个元素吗?

该错误似乎仅在使用标志表情符号时发生。


阅读 305

收藏
2020-07-07

共1个答案

一尘不染

Swift 4(Xcode 9)更新

从Swift 4开始(通过Xcode 9 beta测试),根据Unicode 9标准的规定,每隔一个区域指示器符号,字素簇就会断开:

let str1 = "🇩🇪🇩🇪🇩🇪🇩🇪🇩🇪"
print(str1.count) // 5
print(Array(str1)) // ["🇩🇪", "🇩🇪", "🇩🇪", "🇩🇪", "🇩🇪"]

同样String也是其字符的集合,因此可以使用来获得字符数str1.count


(Swift 3及更高版本的旧答案:)

“3个字形群集边界”
的“标准附件#29 Unicode文本分割”(强调):

传统字素簇定义为基数(例如A或カ),后跟零个或多个连续字符。一种考虑方式是将字符序列形成一个“堆栈”。

基数可以是单个字符,也可以是形成hangul音节的任何Hangul Jamo字符序列(如Unicode标准中的D133所定义),也可以
是Regional_Indicator(RI)字符的任何序列
。RI字符成对使用,以表示与ISO国家代码相对应的Emoji表情符号。超过两个RI字符的序列 应由其他字符分隔 ,例如U + 200B
ZWSP。

(感谢@rintaro提供链接)。

Swift字符表示扩展的字素簇,因此(根据此参考资料)将区域指示符符号的任何序列都计为单个字符是正确的。

您可以用零宽度非JOINER分隔“标志”:

let str1 = "🇩🇪\u{200C}🇩🇪"
print(str1.characters.count) // 2

或插入零宽度空间:

let str2 = "🇩🇪\u{200B}🇩🇪"
print(str2.characters.count) // 3

这也解决了可能的歧义,例如,“🇫”是“🇫”还是“🇫🇷”?

另请参见如何知道两个表情符号是否将显示为一个表情符号?关于一种可能的方法,该方法可以计算Swift字符串中“组成字符”的数量,该方法将返回5给您let str1 = "🇩🇪🇩🇪🇩🇪🇩🇪🇩🇪"

2020-07-07