swift - 对 Hashable 的条件一致性

标签 swift conditional protocols

在 Xcode 10 和 Swift 4.2 中,还有其他类型符合 Hashable,只要它们的元素也符合 Hashable(Array字典等)。

我目前在我的项目中有一些代码为 Swift 4.1 及以下版本添加 Hashable 一致性,如下所示:

extension Array: Hashable where Element: Hashable {
  public var hashValue: Int {
    let prime = 31
    var result = 1
    for element in self {
      result = prime * result + element.hashValue
    }
    return result
  }
}

但是,即使我在代码周围添加了 #if !swift(>=4.2),我仍然会在 Xcode 中看到相同的警告。

Xcode 10 Hashable Warning

我的问题是,如何在 Swift 4.1 及更低版本中保持对 Hashable 的条件一致性,但对 Swift 4.2 消除警告?

最佳答案

条件编译语句#if swift(...) 检查您正在运行的语言版本can differ from the compiler (and therefore standard library) version .

在你的情况下,听起来你正在 Swift 4 兼容模式下使用 Swift 4.2 编译器,这给你一个 language version of 4.1.50 .因此,这会通过条件编译语句并且您的扩展已编译,从而为您提供重复的一致性。

为了检查低于 4.2 的编译器版本,您需要:

// less than 4.2 in Swift 4 compat mode and (less than 4.2 in 3 compat mode or
// greater than 4).
#if !swift(>=4.1.50) && (!swift(>=3.4) || swift(>=4.0))
extension Array : Hashable where Element : Hashable {
  public var hashValue: Int {
    let prime = 31
    var result = 1
    for element in self {
      result = prime * result + element.hashValue
    }
    return result
  }
}
#endif

the new #if compiler directive 会好很多,从 Xcode 10 beta 4 开始在 Swift 4.2 中可用(confirmed by @MartinR)。这样,您就可以直接测试编译器版本,而忽略它可能运行的任何兼容模式。

这对您的具体情况没有帮助,因为您需要 Swift 4.2 和 4.1 编译器都能理解代码(正如 Martin 所指出的),但是对于 future 的兼容性问题,您可以使用 # if !compiler(>=5) 以便仅在使用 4.2 编译器时编译代码块。

关于swift - 对 Hashable 的条件一致性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51450496/

相关文章:

swift - 如何使 View 响应触摸(而不是点击)

ios - CLCircularRegion didEnterRegion 不起作用

java - 如何将 if-else 语句与函数返回一起使用?

linux - 什么是 H.450.2?当它不存在时会发生什么?

google-chrome - 什么是 text/ping,这是一个新标准吗?它依赖于浏览器吗?

swift - swift 中 "precondition"和 "assert"之间的区别?

ios - Swift Jump Method 物体与地面碰撞

bash - IF ELSE声明

Android lint 错误? : conditional operator operator

arrays - 我应该遵循哪种协议(protocol)才能在 Swift 中将一个通用值添加到另一个通用值?