Access an enum value by its hashvalue?
枚举具有名为"hashvalue"的属性,该属性是枚举内的索引。
现在我的问题是,是否可以使用数字访问其值?例:
如果要将枚举值映射为整数,则应直接使用原始值进行映射。例如(来自Swift编程语言:枚举):
1 2 3 4 5 | enum Planet: Int { case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune } let possiblePlanet = Planet(rawValue: 7) |
我不相信有任何文档承诺枚举的hashvalue是任何特别的东西(如果您有链接,我非常感兴趣)。如果没有,您应该在原始值的分配中显式地进行分配。
1 2 3 4 5 6 7 8 9 10 11 | enum Opponent: String { case Player case Computer static func fromHashValue(hashValue: Int) -> Opponent { if hashValue == 0 { return .Player } else { return .Computer } } |
}
说明:
由于无法从其hashvalue中获取枚举值,因此必须手动执行该操作。它不漂亮,但很管用。实际上,您创建了一个函数,它允许您传入所需值的索引,并手动将枚举值返回给调用方。这可能会让一个枚举与吨案件,但它像一个魅力为我工作。
Swift 4,iOS 12:
只需使用显式设置原始类型的枚举(如下面的示例中的
1 2 3 4 5 6 | enum OrderStatus: Int { case noOrder case orderInProgress case orderCompleted case orderCancelled } |
用途:
1 2 3 4 5 6 | var orderStatus: OrderStatus = .noOrder // default value print(orderStatus.rawValue) // it will print 0 orderStatus = .orderCompleted print(orderStatus.rawValue) // it will print 2 |
事实上,对于swift 4.2,
编辑:刚刚找到了一个更安全的方法。您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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中,使用原始内存中的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 ! |
您的要求是让这一行代码工作,其中
1 | let variable:AnEnum = 0 |
这只需使您的枚举
1 2 3 4 5 6 7 | extension AnEnum: CaseIterable, ExpressibleByIntegerLiteral { typealias IntegerLiteralType = Int public init(integerLiteral value: IntegerLiteralType) { self = AnEnum.allCases.first { $0.hashValue == value }! } } |
斯威夫特4.2??(基于@stephen paul之前的回答)
此答案使用switch而不是if/else子句。并返回可选的,因为不保证提供的哈希匹配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | enum CellType:String{ case primary,secondary,tierary /** * NOTE: Since there is no way to get back an enum value from its hashValue, you have to do it manually. * EXAMPLE: CellType.fromHashValue(hashValue: 1)?.rawValue//??primary */ static func fromHashValue(hashValue: Int) -> CellType? { switch hashValue { case 0: return .primary case 1: return .secondary case 2: return .tierary default: return nil } } } |