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

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


当前回答

带索引的Enum

enum eEventTabType : String {
    case Search     = "SEARCH"
    case Inbox      = "INBOX"
    case Accepted   = "ACCEPTED"
    case Saved      = "SAVED"
    case Declined   = "DECLINED"
    case Organized  = "ORGANIZED"

    static let allValues = [Search, Inbox, Accepted, Saved, Declined, Organized]
    var index : Int {
       return eEventTabType.allValues.indexOf(self)!
    }
}

计数:eEventTabType.allValues.count

index: objeceventtabtype .index

享受:)

其他回答

如果你不想在最后一个枚举中创建你的代码,你可以在枚举中创建这个函数。

func getNumberOfItems() -> Int {
    var i:Int = 0
    var exit:Bool = false
    while !exit {
        if let menuIndex = MenuIndex(rawValue: i) {
            i++
        }else{
            exit = true
        }
    }
    return i
}

我为自己解决了这个问题,创建了一个协议(EnumIntArray)和一个全局实用函数(EnumIntArray),可以很容易地将“All”变量添加到任何enum(使用swift 1.2)。“all”变量将包含枚举中所有元素的数组,因此您可以使用all。算一算

它只适用于使用Int类型原始值的枚举,但也许它可以为其他类型提供一些启发。

它还解决了我在上面和其他地方读到的“编号差距”和“迭代时间过多”问题。

其思想是将EnumIntArray协议添加到枚举,然后通过调用EnumIntArray函数定义一个“all”静态变量,并为其提供第一个元素(如果编号有间隙,则为最后一个元素)。

因为静态变量只初始化了一次,所以遍历所有原始值的开销只会对程序造成一次冲击。

示例(无空白):

enum Animals:Int, EnumIntArray
{ 
  case Cat=1, Dog, Rabbit, Chicken, Cow
  static var all = enumIntArray(Animals.Cat)
}

示例(有空格):

enum Animals:Int, EnumIntArray
{ 
  case Cat    = 1,  Dog, 
  case Rabbit = 10, Chicken, Cow
  static var all = enumIntArray(Animals.Cat, Animals.Cow)
}

下面是实现它的代码:

protocol EnumIntArray
{
   init?(rawValue:Int)
   var rawValue:Int { get }
}

func enumIntArray<T:EnumIntArray>(firstValue:T, _ lastValue:T? = nil) -> [T]
{
   var result:[T] = []
   var rawValue   = firstValue.rawValue
   while true
   { 
     if let enumValue = T(rawValue:rawValue++) 
     { result.append(enumValue) }
     else if lastValue == nil                     
     { break }

     if lastValue != nil
     && rawValue  >  lastValue!.rawValue          
     { break }
   } 
   return result   
}

如果实现不反对使用整数enum,你可以添加一个额外的成员值Count来表示枚举中的成员数量-参见下面的例子:

enum TableViewSections : Int {
  case Watchlist
  case AddButton
  case Count
}

现在,您可以通过调用TableViewSections.Count.rawValue来获取枚举中的成员数量,在上面的例子中,它将返回2。

当你在switch语句中处理枚举时,确保在遇到Count成员时抛出断言失败:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  let currentSection: TableViewSections = TableViewSections.init(rawValue:section)!
  switch(currentSection) {
  case .Watchlist:
    return watchlist.count
  case .AddButton:
    return 1
  case .Count:
    assert(false, "Invalid table view section!")
  }
}

此函数依赖于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

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

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