在Xcode 10中,Swift编译器足够聪明,可以:
Treat可选,将describe 'my_method(my_method_argument)' do
include_context 'rake'
it 'calls my method' do
expect(described_class.send(:my_method, my_method_argument)).to eq(expected_results)
end
end
的值包装为Hashable
。
Xcode> = 9.4也将处理包含所有Hashable
的{{1}}
属性也为struct
。
奇怪的是,即使构建语言是Swift 4甚至是Swift 3,Xcode 10也会将Optionals视为Hashable。
以下面的代码为例:
Hashable
该代码在Xcode 10下编译,并且即使构建语言是Swift 3,使用Foo对象的hashValue也会按预期工作!
但是,在Xcode 9.4中,除非您将属性设为非可选属性,否则Foo结构不会自动哈希。
此代码可以按您希望在Xcode 9.4 / Swift 4.1中进行编译和工作:
Hashable
如何在Xcode 9中使可选项struct Foo: Hashable {
var string1: String?
var string2: String?
}
?我当然可以为自己的结构实现struct Foo: Hashable {
var string1: String
var string2: String
}
一致性,但是为多部分结构创建良好的哈希值实际上有点棘手,而且我不必为此担心。
我也想不出一种简单的方法来制作可选的Hashable
。 (再次,这只是Xcode
答案 0 :(得分:2)
Swift 4.2 定义了条件Optional: Hashable
的符合性
Optional.swift
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
,则自动为类型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 Compiler Version Directive):
#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