枚举有一个名为' hashValue'这是它在枚举中的索引。
现在我的问题是,是否可以通过使用数字来访问其值?例如:let variable:AnEnum = 0
答案 0 :(得分:14)
如果要将枚举值映射到整数,则应直接使用原始值。例如(来自Swift Programming Language: Enumerations):
enum Planet: Int {
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
let possiblePlanet = Planet(rawValue: 7)
我不相信有任何文档承诺枚举的hashValue特别是任何东西(如果你有链接,我会非常感兴趣)。如果没有,你应明确指定原始值。
答案 1 :(得分:10)
enum Opponent: String {
case Player
case Computer
static func fromHashValue(hashValue: Int) -> Opponent {
if hashValue == 0 {
return .Player
} else {
return .Computer
}
}
}
<强>解释强>
由于无法从hashValue中获取枚举值,因此必须手动执行。它不漂亮,但它的工作原理。您实际上创建了一个函数,允许您传入所需值的索引并手动将该枚举值返回给调用者。这可能会因为大量案例的枚举而变得令人讨厌,但它对我来说就像是一种魅力。
答案 2 :(得分:0)
此答案使用switch而不是if / else子句。并返回可选值,因为您不保证所提供的哈希将匹配。
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
}
}
}
答案 3 :(得分:0)
您的要求是运行以下代码行,其中0
是枚举变量的hashValue
(请注意,从Xcode 10开始,0
永远不是有效的hashValue。 ..):
let variable:AnEnum = 0
只需将枚举设置为ExpressibleByIntegerLiteral
和CaseIterable
即可完成
extension AnEnum: CaseIterable, ExpressibleByIntegerLiteral {
typealias IntegerLiteralType = Int
public init(integerLiteral value: IntegerLiteralType) {
self = AnEnum.allCases.first { $0.hashValue == value }!
}
}
CaseIterable
协议在Swift 4.2中是本机可用的,您可以使用https://stackoverflow.com/a/49588446/1033581中的代码针对较早的swift版本(Swift 3.x,4.x)自己实现。
答案 4 :(得分:0)
实际上,在Swift 4.2中,hashValue
不再是enum
内部的索引。
编辑:刚刚找到了一种更安全的方法来实现这一目标。您可以使用CaseIterable
(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 !
答案 5 :(得分:0)
iOS 4的Swift 4:
只需通过显式设置原始类型(如下面的示例中的Int
)即可使枚举:
enum OrderStatus: Int {
case noOrder
case orderInProgress
case orderCompleted
case orderCancelled
}
用法:
var orderStatus: OrderStatus = .noOrder // default value
print(orderStatus.rawValue) // it will print 0
orderStatus = .orderCompleted
print(orderStatus.rawValue) // it will print 2