'===' & '!==' in Swift

一篇简短的小记。

Start

由于最近比较多的用了 IGListKit 来写新的模块和重构旧的模块,其中 IGListKit 要求模型遵遁 IGListDiffable 协议,其中需要你实现一个函数:

1
public func isEqual(toDiffableObject object: IGListDiffable?) -> Bool

来告诉 IGList 接收到的和给定的 object 是否相等。一般情况用模型里的 hash id 来判断就可以解决,但今天和师傅讨论到如果是一个数组,而且数组里的模型又没有 ID 属性,该如何判断相等。

由此想到了 ‘===’ & ‘!==’ 运算符。

‘===’ & ‘!==’

比起常用的 == 和 != ,这两个运算貌似使用的频度非常低,其实用法倒是很简单的, === 和 !== 用于比较 引用类型(Reference Type)是否是相同的引用。

不过随便查看几个搜索结果会发现好像有这么一段说法:

“Check whether two arrays or subarrays share the same storage and elements by comparing them with the identity operators (=== and !==).”

嗯嗯嗯?还可以比较数组或者子数组的?原生支持?如此方便?
在 Playground 中简单一试:

1
2
3
4
let array1 = [1, 2, 3]
var array2 = array1
array1 !== array2

马上就会 “Error: binary operator ‘!==’ cannot be applied to…”。

不过等等,Swift 中的 Array 不是 Value Type 吗,是应该不能用这个啊,那为什么会有可以比较数组这种说法?难道记错了?

“Array and Dictionary in Swift are implemented as structs.”

没记错, Array 是 Value Type.

后来发现,之所以有比较数组这种说法是因为,在 2014 年 Swift beta 3 之前,Swift 中的 Array 有一些小小的不同,引用喵神以前的博客里的一句话:

“Swift 考虑到实际使用的情景,对 Array 做了特殊的处理。除非需要(比如 Array 的大小发生改变,或者显式地要求进行复制),否则 Array 在传递的时候会使用参照。”

而之后

“对于 Array 中元素的改变,在 beta 3 中发生了变化。现在不再存在作为一个值类型但是却在赋值和改变时表现为参照类型的 Array 的特例,而是彻头彻尾表现出了值类型的特点。”

所以, ‘===’ & ‘!==’ 用于比较数组的这种说法也是很早之前的老文档中存在的,现在并不能用啦。

等等,谁说不能?

1
2
3
4
let array1 = NSArray(array: [A, B])
var array2 = array1
array1 !== array2

用 Cocoa 中的容器类自然没问题,因为是引用类嘛。

但这就没有 Swift 的 “钦定” 感了! 🙃

善变的 Swift! 🙃

Swift 3.1

Xcode 8.3 出来了! Swift 3.1 出来了!
Apple 还说 “Faster builds for large projects that mix Objective-C and Swift code”!
赶紧一试!

Markdown preferences pane

120 秒… 还有 Swift 3.1 附赠的爆炸多的警告… 🙃
也许还是在提示我电脑不行了。 🙃

相关链接

Apple - Classes and Structures
OneV’s Den - 行走于 Swift 的世界中