如何确定Swift enum中的案例数?
(我希望避免手动枚举所有值,或者如果可能的话使用旧的“enum_count技巧”。)
如何确定Swift enum中的案例数?
(我希望避免手动枚举所有值,或者如果可能的话使用旧的“enum_count技巧”。)
当前回答
此函数依赖于2个未记录的当前(Swift 1.1) enum行为:
枚举的内存布局只是一个大小写索引。如果case count为2 ~ 256,则为UInt8。 如果枚举从无效的大小写索引进行位转换,则其hashValue为0
所以请自担风险使用:)
func enumCaseCount<T:Hashable>(t:T.Type) -> Int {
switch sizeof(t) {
case 0:
return 1
case 1:
for i in 2..<256 {
if unsafeBitCast(UInt8(i), t).hashValue == 0 {
return i
}
}
return 256
case 2:
for i in 257..<65536 {
if unsafeBitCast(UInt16(i), t).hashValue == 0 {
return i
}
}
return 65536
default:
fatalError("too many")
}
}
用法:
enum Foo:String {
case C000 = "foo"
case C001 = "bar"
case C002 = "baz"
}
enumCaseCount(Foo) // -> 3
其他回答
或者你可以在枚举之外定义_count,并静态地附加它:
let _count: Int = {
var max: Int = 0
while let _ = EnumName(rawValue: max) { max += 1 }
return max
}()
enum EnumName: Int {
case val0 = 0
case val1
static let count = _count
}
这样,不管你创建了多少个枚举,它只会被创建一次。
(如果是静态的,就删除这个答案)
只是想共享一个解决方案时,你有一个枚举与相关的值。
enum SomeEnum {
case one
case two(String)
case three(String, Int)
}
CaseIterable不会自动提供allcase。 我们不能为枚举提供像Int这样的原始类型来计算case计数。
我们能做的是使用开关的功率和通过关键字。
extension SomeEnum {
static var casesCount: Int {
var sum = 0
switch Self.one { // Potential problem
case one:
sum += 1
fallthrough
case two:
sum += 1
fallthrough
case three:
sum += 1
}
return sum
}
}
现在你可以说someenume。casescount。
备注:
赛尔夫开关还是有问题。一个{…,我们硬编码了第一个案例。您可以很容易地破解这个解决方案。但我只是将它用于单元测试,所以这不是问题。 如果您经常需要在枚举中获得带有关联值的case计数,请考虑代码生成。
大家好,单元测试呢?
func testEnumCountIsEqualToNumberOfItemsInEnum() {
var max: Int = 0
while let _ = Test(rawValue: max) { max += 1 }
XCTAssert(max == Test.count)
}
这与安东尼奥的解决方案相结合:
enum Test {
case one
case two
case three
case four
static var count: Int { return Test.four.hashValue + 1}
}
在主代码中给你O(1),加上如果有人添加了enum case 5并且没有更新count的实现,你会得到一个失败的测试。
它可以使用一个静态常量,其中包含枚举的最后一个值加1。
enum Color : Int {
case Red, Orange, Yellow, Green, Cyan, Blue, Purple
static let count: Int = Color.Purple.rawValue + 1
func toUIColor() -> UIColor{
switch self {
case .Red:
return UIColor.redColor()
case .Orange:
return UIColor.orangeColor()
case .Yellow:
return UIColor.yellowColor()
case .Green:
return UIColor.greenColor()
case .Cyan:
return UIColor.cyanColor()
case .Blue:
return UIColor.blueColor()
case .Purple:
return UIColor.redColor()
}
}
}
为什么要把事情搞得这么复杂?Int enum最简单的计数器是添加:
病例数
最后。和…维奥拉,现在你有计数了,又快又简单