swift - 如何在 Xcode 9.4 中使 Optionals 可散列
问题描述
在 Xcode 10 中,Swift 编译器足够智能:
Hashable
将包装值的Optionals视为 isHashable
。Xcode >=9.4 也将
struct
包含所有Hashable
属性的 s 也视为Hashable
.
奇怪的是,即使构建语言是 Swift 4,甚至是 Swift 3,Xcode 10 也将 Optionals 视为 Hashable。
以下面的代码为例:
struct Foo: Hashable {
var string1: String?
var string2: String?
}
该代码在 Xcode 10 下编译,并且使用 Foo 对象的 hashValue 可以按预期工作,即使构建语言是 Swift 3!
但是,在 Xcode 9.4 中,除非您将属性设为非可选,否则 Foo 结构不会自动 Hashable。
这段代码可以按照您在 Xcode 9.4/Swift 4.1 中的要求编译和工作:
struct Foo: Hashable {
var string1: String
var string2: String
}
如何Hashable
在 Xcode 9 中创建选项?我当然可以自己为我的结构实现Hashable
一致性,但是为多部分结构创建好的散列实际上有点棘手,我不想担心它。
我也想不出一种直接的方法来制作 Optional Hashable
。(同样,这只是 Xcode < Xcode 10 中的一个问题。我的雇主还没有搬到 Xcode 10,所以我需要一个适用于 Xcode 9.4 的解决方案)
解决方案
Swift 4.2将Optional.swift中的条件Optional: Hashable
一致性
定义
为
extension Optional: Hashable where Wrapped: Hashable {
// ...
public func hash(into hasher: inout Hasher) {
switch self {
case .none:
hasher.combine(0 as UInt8)
case .some(let wrapped):
hasher.combine(1 as UInt8)
hasher.combine(wrapped)
}
}
}
尤其是
.none
具有与整数零相同的哈希值,与类型无关,并且- 哈希值
.some(wrapped)
是通过将 的哈希值wrapped
与整数 1 的哈希值混合得到的。
Swift 4.1(Xcode 9.4 附带)已经拥有实现类似方法的必要工具:
条件一致性,即我们可以定义一个扩展
extension Optional: Hashable where Wrapped: Hashable
如果所有成员都是 ,则自动合成
Hashable
for 类型Hashable
。
这是一个可能的实现:
extension Optional: Hashable where Wrapped: Hashable {
struct Combiner: Hashable {
let left: Int
let right: Wrapped
}
public var hashValue: Int {
switch self {
case .none:
return 0.hashValue
case .some(let wrapped):
return Combiner(left: 1, right: wrapped).hashValue
}
}
}
例子:
struct Foo: Hashable {
var string1: String?
var string2: String?
}
let foo = Foo(string1: "1", string2: "2")
print(foo.hashValue) // 2171695307022640119
为了使这段代码也可以在 Swift 4.2 和更新版本中编译,可以有条件地编译扩展方法(比较 SE-0212 编译器版本指令):
#if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
// Code targeting the Swift 4.2 compiler and above:
// Conditional conformance `Optional: Hashable` defined in the standard library.
#elseif swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
// Code targeting the Swift 4.1 compiler and above:
extension Optional: Hashable where Wrapped: Hashable {
// ...
}
#endif
推荐阅读
- excel - 发送短信的 VBA 问题
- sql - 如何从最终表中的嵌套 SELECT 查询中返回列?
- codenameone - 使用 Infinite Container pull to refresh 实现安全区域
- repository - openSUSE zypper 错误 - 在指定 URL 未找到有效元数据,无法确定存储库类型
- google-apps-script - 将单元格数据发送到 Google 表格中的自定义函数
- css - Flexbox:当img太大且高度为100%时,flex 1变得太大
- sql-server - 如何在 SQL Server Management Studio 中生成排序脚本?
- docker - Kubernetes 上 Jenkins 的持久卷
- javascript - 对象没有出现在 JS 中
- java - 使用 alpha 属性设置 View alpha 或为背景属性添加合适的值是否重要?