Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.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 是否通过其哈希值访问枚举值?_Swift_Enums - Fatal编程技术网

Swift 是否通过其哈希值访问枚举值?

Swift 是否通过其哈希值访问枚举值?,swift,enums,Swift,Enums,enum有一个名为“hashValue”的属性,该属性是其在enum中的索引 现在我的问题是,是否可以使用数字访问其值?例如:let变量:AnEnum=0如果要将枚举值映射到整数,则应直接使用原始值。例如(来源于): 我不相信有任何文档承诺enum的hashValue是特别的(如果您有链接,我会非常感兴趣)。如果没有,那么在分配原始值时应该是明确的 enum Opponent: String { case Player case Computer static func fr

enum有一个名为“hashValue”的属性,该属性是其在enum中的索引


现在我的问题是,是否可以使用数字访问其值?例如:
let变量:AnEnum=0

如果要将枚举值映射到整数,则应直接使用原始值。例如(来源于):

我不相信有任何文档承诺enum的hashValue是特别的(如果您有链接,我会非常感兴趣)。如果没有,那么在分配原始值时应该是明确的

enum Opponent: String {
   case Player
   case Computer

   static func fromHashValue(hashValue: Int) -> Opponent {
       if hashValue == 0 {
           return .Player
       } else {
           return .Computer
       }
   }
}

说明:

var orderStatus: OrderStatus = .noOrder // default value 

print(orderStatus.rawValue) // it will print 0

orderStatus = .orderCompleted
print(orderStatus.rawValue) // it will print 2

由于无法从其hashValue中获取枚举值,因此必须手动执行此操作。虽然不漂亮,但它很管用。实际上,您创建了一个函数,该函数允许您传入所需值的索引,并手动将该枚举值返回给调用者。这可能会让一个有大量案例的枚举变得很糟糕,但它对我来说很有吸引力。

Swift 4.2您的要求是让这行代码正常工作,其中
0
是枚举变量的
hashValue
(请注意,从Xcode 10开始,
0
永远不是有效的hashValue…):

只需将枚举
设置为可表达的ebyintegerliteral
案例可表达即可:

extension AnEnum: CaseIterable, ExpressibleByIntegerLiteral {
    typealias IntegerLiteralType = Int

    public init(integerLiteral value: IntegerLiteralType) {
        self = AnEnum.allCases.first { $0.hashValue == value }!
    }
}

caseitrable
协议在Swift 4.2中本机可用,您可以使用中的代码为较旧的Swift版本(Swift 3.x,4.x)自行实现。

事实上,在Swift 4.2中,
hashValue
不再是
枚举
中的索引

编辑:刚刚找到了一种更安全的方法来实现这一点。您可以使用
caseitrable
(Swift 4.2)并在
allCases
集合中选择所需的案例

enum Foo: CaseIterable {
  case bar
  case baz

  init?(withIndex index: Int) {
    guard Foo.allCases.indices ~= index else { return nil }
    self = Foo.allCases[index]
  }
}

Foo(withIndex: 0) // bar
Foo(withIndex: 1) // baz
Foo(withIndex: 2) // nil
注意:我将这个小把戏留在这里,因为玩不安全指针很有趣,但是请不要使用此方法创建带有索引的案例。 它依赖于Swift内存表示,它可能会在不通知的情况下更改,这是非常不安全的,因为使用错误的索引会产生运行时错误

也就是说,在Swift中,案例是使用原始内存中的
Int
表示的。因此,您可以使用它来使用不安全的指针构建案例

enum Foo {
  case bar
  case baz

  init(withIndex index: UInt8) {
    var temp: Foo = .bar
    withUnsafeMutablePointer(to: &temp) { pointer in
      let ptr = UnsafeMutableRawPointer(pointer).bindMemory(to: UInt8.self, capacity: 1)
      ptr.pointee = index
    }

    self = temp
  }
}

Foo(withIndex: 0) // bar
Foo(withIndex: 1) // baz
Foo(withIndex: 2) // runtime error !

Swift 4,iOS 12:

var orderStatus: OrderStatus = .noOrder // default value 

print(orderStatus.rawValue) // it will print 0

orderStatus = .orderCompleted
print(orderStatus.rawValue) // it will print 2
只需显式设置原始类型(如下面示例中的
Int
)即可创建枚举:

用法:

var orderStatus: OrderStatus = .noOrder // default value 

print(orderStatus.rawValue) // it will print 0

orderStatus = .orderCompleted
print(orderStatus.rawValue) // it will print 2

我的枚举是CGPoints的枚举。什么是“CGPoints的枚举”?enum AnEnum:CGPoint{},对不起,我的单词选择不好,我的意思是说“我的枚举是CGPoint类型的枚举”;)那还可以编译吗?您应该得到“原始类型'CGPoint'不能从任何文本转换。”。。。在我看来,这实际上是将枚举重载得太远了,并且在边缘情况下可能会产生许多奇怪的编译器错误。但是如果您被限制在其中,那么实现
static func fromRaw(x:Int)->AnEnum?
来完成您想要它做的事情
hashValue
没有任何承诺。一些解释性文本可以将此代码块转换为一个好的答案。检查apple doc隐式分配的原始值示例
enum CompassPoint:String{
@LeoDabus嗯,我想我每天都会学到一些新东西。我非常感谢你向我指出这一点+1@StephenPaul您还可以扩展枚举并创建一个看起来很棒的初始值设定项@LeoDabus。我将更新我的答案以反映您的建议。hashValue只是从Xcode 6到Xcode 9的索引。在Xcode 10构建中,hashValue与索引无关。换句话说:这个问题已经失去了它的价值。从doc来看,很明显,您不能依赖哈希值作为索引:“哈希值不能保证在程序的不同执行过程中相等。”
var orderStatus: OrderStatus = .noOrder // default value 

print(orderStatus.rawValue) // it will print 0

orderStatus = .orderCompleted
print(orderStatus.rawValue) // it will print 2