一个重要的点是,Swift中字符串的==
可能与Objective-C中的-isEqualToString:
不等价。其特殊之处在于Swift和Objective-C之间字符串表示方式的差异。
看一个例子:
let composed = "Ö"
let decomposed = composed.decomposedStringWithCanonicalMapping
composed.utf16.count
decomposed.utf16.count
let composedNSString = composed as NSString
let decomposedNSString = decomposed as NSString
decomposed == composed
decomposedNSString == composedNSString
NSString
是由一系列UTF-16代码单元表示的(可大致理解为UTF-16(定宽)代码单元数组)。而Swift的String
概念上是“字符”的序列,其中“字符”是抽象的扩展字形集群(读作Character = 任意数量的Unicode代码点,通常是用户看到的字符和文本输入光标跳转的位置)。
接下来要提到的是Unicode。对于它有很多要写的,但在这里我们感兴趣的是所谓的“规范等价”。使用Unicode代码点,视觉上相同的“字符”可以以多种方式进行编码。例如,“Á”可以被表示为一个预先组合的“Á”,也可以是一个分解的A + ◌́(这就是为什么示例中composed.utf16
和decomposed.utf16
具有不同长度的原因)。阅读关于这个内容的好文章,可以查看这篇精彩的文章。
-[NSString isEqualToString:]
,根据文档,逐个比较NSString
的代码单元,所以:
[Á] != [A, ◌́]
Swift的String ==
会通过规范等价比较字符。
[ [Á] ] == [ [A, ◌́] ]
在Swift中,上述示例将对字符串返回true。这就是为什么`-[NSString isEqualToString:]`不等同于Swift的String ==。可以通过比较字符串的UTF-16视图来进行等效的纯Swift比较:
decomposed.utf16.elementsEqual(composed.utf16)
decomposedNSString == composedNSString
decomposedNSString.isEqual(to: composedNSString as String)
此外,在Swift中NSString == NSString
和String == String
之间存在差异。 NSString ==
将导致使用isEqual和UTF-16代码单元逐个比较,而String ==
将使用规范等价性:
decomposed == composed
decomposed as NSString == composed as NSString
整个示例代码如下:
let composed = "Ö"
let decomposed = composed.decomposedStringWithCanonicalMapping
composed.utf16.count
decomposed.utf16.count
let composedNSString = composed as NSString
let decomposedNSString = decomposed as NSString
decomposed == composed
decomposedNSString == composedNSString
decomposed.utf16.elementsEqual(composed.utf16)
decomposedNSString == composedNSString
decomposedNSString.isEqual(to: composedNSString as String)
===
是身份运算符,而==
则是相等运算符(默认情况下在 NSObject 及其子类上调用isEqual:
方法)。 - Bryan Chen“String”不符合协议“AnyObject”。
- user1040049String
比较的。Xcode 6.4会返回错误Binary operator '===' cannot be applied to two String operands
。 - Dima Deplov