如何确定Swift enum中的案例数?

(我希望避免手动枚举所有值,或者如果可能的话使用旧的“enum_count技巧”。)


当前回答

enum EnumNameType: Int {
    case first
    case second
    case third

    static var count: Int { return EnumNameType.third.rawValue + 1 }
}

print(EnumNameType.count) //3

OR

enum EnumNameType: Int {
    case first
    case second
    case third
    case count
}

print(EnumNameType.count.rawValue) //3

*在Swift 4.2 (Xcode 10)可以使用:

enum EnumNameType: CaseIterable {
    case first
    case second
    case third
}

print(EnumNameType.allCases.count) //3

其他回答

为什么要把事情搞得这么复杂?Int enum最简单的计数器是添加:

病例数

最后。和…维奥拉,现在你有计数了,又快又简单

enum EnumNameType: Int {
    case first
    case second
    case third

    static var count: Int { return EnumNameType.third.rawValue + 1 }
}

print(EnumNameType.count) //3

OR

enum EnumNameType: Int {
    case first
    case second
    case third
    case count
}

print(EnumNameType.count.rawValue) //3

*在Swift 4.2 (Xcode 10)可以使用:

enum EnumNameType: CaseIterable {
    case first
    case second
    case third
}

print(EnumNameType.allCases.count) //3

Swift 3版本使用Int类型枚举:

protocol CaseCountable: RawRepresentable {}
extension CaseCountable where RawValue == Int {
    static var count: RawValue {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) { i += 1 }
        return i
    }
}

演职员名单:本文基于bzz和Nate Cook的回答。

泛型IntegerType(在Swift 3中重命名为Integer)不受支持,因为它是一个严重碎片化的泛型类型,缺少很多函数。继任者在Swift 3中不再可用。

注意代码指挥官对Nate Cooks回答的注释仍然有效:

虽然这很好,因为您不需要硬编码一个值,但这会 每次调用枚举值时实例化每个枚举值。这是O(n) 而不是O(1)

据我所知,由于泛型类型中不支持静态存储属性,因此在使用此作为协议扩展时(并且没有像Nate Cook那样在每个枚举中实现)目前没有解决方案。

无论如何,对于小枚举,这应该不是问题。一个典型的用例就是section。如Zorayr所提到的UITableViews。

我定义了一个可重用的协议,它根据Nate Cook发布的方法自动执行案例计数。

protocol CaseCountable {
    static var caseCount: Int { get }
}

extension CaseCountable where Self: RawRepresentable, Self.RawValue == Int {
    internal static var caseCount: Int {
        var count = 0
        while let _ = Self(rawValue: count) {
            count += 1
        }
        return count
    }
}

然后我可以重用这个协议,例如:

enum Planet : Int, CaseCountable {
    case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
//..
print(Planet.caseCount)

只是想共享一个解决方案时,你有一个枚举与相关的值。

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计数,请考虑代码生成。