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

时间:2014-11-11 10:06:27

标签: ios swift unicode emoji countelements

let str1 = ""
let str2 = "....."

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

结果:1​​,10

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

这个错误似乎只发生在我使用标志表情符号时。

2 个答案:

答案 0 :(得分:21)

更新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 Grapheme Cluster Boundaries" 在“标准附件#29 UNICODE TEXT SEGMENTATION”中: (重点补充):

  

遗留字形簇被定义为基础(例如A或カ)   后跟零个或多个连续字符。一种思考方式   这是一系列形成“堆叠”的字符。

     

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

(感谢@rintaro的链接)。

Swift Character代表一个扩展的字形集群,因此它是(根据 对此参考)纠正任何区域指标符号序列 被算作单个字符。

您可以通过ZERO WIDTH NON-JOINER分隔“标志”:

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

或插入ZERO WIDTH SPACE:

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

这也解决了可能的歧义,例如:应该“” 是“”还是“”?

另请参阅How to know if two emojis will be displayed as one emoji?有关可能的方法 计算Swift字符串中“组合字符”的数量, 这将为5返回let str1 = ""

答案 1 :(得分:4)

以下是我解决这个问题的方法,对于 Swift 3

let str = "" //or whatever the string of emojis is
let range = str.startIndex..<str.endIndex
var length = 0
str.enumerateSubstrings(in: range, options: NSString.EnumerationOptions.byComposedCharacterSequences) { (substring, substringRange, enclosingRange, stop) -> () in
        length = length + 1
    }
print("Character Count: \(length)")

这解决了字符数和表情符号的所有问题,是我找到的最简单的方法。