重要的一点是Swift在字符串上的==可能并不等同于Objective-C的-isEqualToString:。其特点在于Swift和Objective-C之间字符串的表示方式不同。
看看这个例子:
let composed = "Ö" // U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS
let decomposed = composed.decomposedStringWithCanonicalMapping // (U+004F LATIN CAPITAL LETTER O) + (U+0308 COMBINING DIAERESIS)
composed.utf16.count // 1
decomposed.utf16.count // 2
let composedNSString = composed as NSString
let decomposedNSString = decomposed as NSString
decomposed == composed // true, Strings are equal
decomposedNSString == composedNSString // false, NSStrings are not
NSString被表示为UTF-16编码单元序列(大致读取为UTF-16(固定宽度)编码单元数组)。而Swift字符串在概念上是“字符”的序列,其中“字符”是抽象扩展的字形集群(读取字符=任何数量的Unicode码点,通常是用户看到的字符和文本输入游标跳跃)。
下一个要提到的是Unicode。关于它有很多可写的,但这里我们感兴趣的是所谓的“规范等价”。使用Unicode码位,从视觉上看,相同的“字符”可以用多种方式进行编码。例如,“Á”可以表示为预先组合的“Á”或分解的a +◌(这就是为什么在示例中组合。Utf16和分解。Utf16有不同的长度)。阅读这篇很棒的文章是一件好事。
-[NSString isEqualToString:],根据文档,比较NSString的代码单元,因此:
[Á] != [A, ◌́]
Swift的String ==根据规范等价性比较字符。
[ [Á] ] == [ [A, ◌́] ]
在swift中,上面的例子将为Strings返回true。这就是为什么-[NSString isEqualToString:]不等同于Swift的String ==。等价的纯Swift比较可以通过比较String的UTF-16视图来完成:
decomposed.utf16.elementsEqual(composed.utf16) // false, UTF-16 code units are not the same
decomposedNSString == composedNSString // false, UTF-16 code units are not the same
decomposedNSString.isEqual(to: composedNSString as String) // false, UTF-16 code units are not the same
另外,在Swift中NSString == NSString和String == String是有区别的。NSString ==将导致isEqual和UTF-16代码单元逐个代码单元的比较,其中as String ==将使用规范等价:
decomposed == composed // true, Strings are equal
decomposed as NSString == composed as NSString // false, UTF-16 code units are not the same
整个例子是:
let composed = "Ö" // U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS
let decomposed = composed.decomposedStringWithCanonicalMapping // (U+004F LATIN CAPITAL LETTER O) + (U+0308 COMBINING DIAERESIS)
composed.utf16.count // 1
decomposed.utf16.count // 2
let composedNSString = composed as NSString
let decomposedNSString = decomposed as NSString
decomposed == composed // true, Strings are equal
decomposedNSString == composedNSString // false, NSStrings are not
decomposed.utf16.elementsEqual(composed.utf16) // false, UTF-16 code units are not the same
decomposedNSString == composedNSString // false, UTF-16 code units are not the same
decomposedNSString.isEqual(to: composedNSString as String) // false, UTF-16 code units are not the same