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