Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 如何使用Xcode 10中可用的API使枚举符合Hashable?_Swift_Xcode10_Swift4.2_Hashable - Fatal编程技术网

Swift 如何使用Xcode 10中可用的API使枚举符合Hashable?

Swift 如何使用Xcode 10中可用的API使枚举符合Hashable?,swift,xcode10,swift4.2,hashable,Swift,Xcode10,Swift4.2,Hashable,在我的Swift 4.2.1代码中,我有以下枚举: enum MyEnum { case caseOne(Int) case caseTwo(String) case caseThree } 它符合equalable: extension MyEnum: Equatable { static func == (lhs: MyEnum, rhs: MyEnum) -> Bool { switch (lhs, rhs) {

在我的Swift 4.2.1代码中,我有以下枚举:

enum MyEnum {

    case caseOne(Int)
    case caseTwo(String)
    case caseThree
}
它符合
equalable

extension MyEnum: Equatable {

    static func == (lhs: MyEnum, rhs: MyEnum) -> Bool {

        switch (lhs, rhs) {
        case (.caseOne, .caseOne), (.caseTwo, .caseTwo), (.caseThree, .caseThree):
            return true
        default:
            return false
        }
    }
}
我需要使其符合可哈希的
,这就是我添加扩展的原因:

extension MyEnum: Hashable {

    var hashValue: Int {

        switch self {
        case .caseOne:
            return 1
        case .caseTwo:
            return 2
        case .caseThree:
            return 3
        }
    }
}
现在我想迁移到Xcode 10中提供的新API。我删除了
hashValue
的实现,并将
哈希的实现添加到:)

你能告诉我我是否正确地切换到了新的API吗?我使用这个测试,如果一切正常,它会打印两次
true

var testDictionary = [MyEnum: Int]()
testDictionary[.caseOne(100)] = 100
testDictionary[.caseOne(1000)] = 1000
testDictionary[.caseTwo("100")] = 100
testDictionary[.caseTwo("1000")] = 1000
let countCaseOne = testDictionary.reduce(0) {
    if case .caseOne = $1.key {
        return $0 + 1
    }
    return $0
} == 1
print(countCaseOne) // true
let countCaseTwo = testDictionary.reduce(0) {
    if case .caseTwo = $1.key {
        return $0 + 1
    }
    return $0
} == 1
print(countCaseTwo) // true

无需手动实现
Hashable
一致性,编译器可以自动合成特定
enum
(其中所有具有关联值的案例都有一个
Hashable
关联值)。您只需要声明一致性

enum MyEnum: Hashable {
    case caseOne(Int)
    case caseTwo(String)
    case caseThree
}

// You don't even need to write `: Equatable`, since automatic Hashable conformance takes care of Equatable too, I just left it there for clarity
extension MyEnum: Equatable {
    static func == (lhs: MyEnum, rhs: MyEnum) -> Bool {
        switch (lhs, rhs) {
        case (.caseOne, .caseOne), (.caseTwo, .caseTwo), (.caseThree, .caseThree):
            return true
        default:
            return false
        }
    }
}

您可以按照另一个答案中的建议使用自动生成的
Hashable
一致性(在您的类型不包含任何非
Hashable
类型的日期的情况下)

但在一般情况下,您可以这样做(自动生成的代码可能也是这样):


你想知道什么?在我看来这是正确的。@Sandeep在教程中,我在
hash(into:)
的实现中看到了类似于
hasher.combine(self.property)
的东西。我没有找到enum的示例。这就是为什么我想知道我的实现是否正确。顺便说一下,你不必自己实现这个方法。语言根据您的属性自行执行。如果enum的所有关联值都是可哈希的(或没有)。@user28434是的,这就是为什么我提到了OP的特定enum,但我会编辑我的答案,使其更一般。谢谢您的回答。但是我忘了写
MyEnum
包含
=
的实现,请检查我更新的答案。@RomanPodymov这没有什么区别,您仍然可以使用自动
哈希表
一致性并覆盖自动合成的
=
方法。检查我的最新答案。顺便说一句,你确定你不关心关联值的相等性吗?@DávidPásztor在我的例子中,我不需要检查关联值。如果没有实现
散列(into:)
的话,我的测试的输出是
/
/
。谢谢你的回答。但是为什么我可以跳过
combine
来处理
.casetree
?因为
hasher
已经有了一些初始状态(我们称之为
seed
),然后
combine(:)
hasher
状态(
seed
初始)执行一些函数,然后执行组合值,结果将替换哈希器的状态。然后,
hasher
的状态转换为
hash
函数结果,该结果可通过
hashValue
属性访问。因此,即使您根本不进行组合,您仍然会得到一个结果。Ofc,如果你有多个
案例
而没有
关联值
,你最好将其与一些
常量
结合起来,否则这些案例的哈希值将是相同的。请检查我编辑过的答案,我将
=
添加到
MyEnum
。因为我不需要检查关联值。@RomanPodymov,嗯,如果您不需要它来进行散列,那么您可以使用答案中的
散列(into:)
实现。
enum MyEnum: Hashable {
    case caseOne(Int)
    case caseTwo(String)
    case caseThree
}

// You don't even need to write `: Equatable`, since automatic Hashable conformance takes care of Equatable too, I just left it there for clarity
extension MyEnum: Equatable {
    static func == (lhs: MyEnum, rhs: MyEnum) -> Bool {
        switch (lhs, rhs) {
        case (.caseOne, .caseOne), (.caseTwo, .caseTwo), (.caseThree, .caseThree):
            return true
        default:
            return false
        }
    }
}
extension MyEnum: Hashable {

    func hash(into hasher: inout Hasher) {

        switch self {
        case .caseOne(let value):
            hasher.combine(value) // combine with associated value, if it's not `Hashable` map it to some `Hashable` type and then combine result
        case .caseTwo(let value):
            hasher.combine(value) // combine with associated value, if it's not `Hashable` map it to some `Hashable` type and then combine result
        case .caseThree:
            // you can `combine` with some `Hashable` constant, but here it's ok just to skip
            break
        }
    }
}