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

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


当前回答

我写了一个简单的扩展,它给所有枚举的原始值是整数一个count属性:

extension RawRepresentable where RawValue: IntegerType {
    static var count: Int {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) {
            i = i.successor()
        }
        return Int(i.toIntMax())
    }
}

不幸的是,它给了计数属性OptionSetType,它不会正常工作,所以这里是另一个版本,需要显式符合CaseCountable协议的任何枚举的情况下,你想要计数:

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

它与Tom Pelaia发布的方法非常相似,但适用于所有整数类型。

其他回答

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

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
}

我写了一个简单的扩展,它给所有枚举的原始值是整数一个count属性:

extension RawRepresentable where RawValue: IntegerType {
    static var count: Int {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) {
            i = i.successor()
        }
        return Int(i.toIntMax())
    }
}

不幸的是,它给了计数属性OptionSetType,它不会正常工作,所以这里是另一个版本,需要显式符合CaseCountable协议的任何枚举的情况下,你想要计数:

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

它与Tom Pelaia发布的方法非常相似,但适用于所有整数类型。

如果实现不反对使用整数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!")
  }
}

我有一篇博客文章详细介绍了这一点,但只要你的枚举的原始类型是一个整数,你可以这样添加一个计数:

enum Reindeer: Int {
    case Dasher, Dancer, Prancer, Vixen, Comet, Cupid, Donner, Blitzen
    case Rudolph

    static let count: Int = {
        var max: Int = 0
        while let _ = Reindeer(rawValue: max) { max += 1 }
        return max
    }()
}

这种函数能够返回枚举的计数。

斯威夫特2:

func enumCount<T: Hashable>(_: T.Type) -> Int {
    var i = 1
    while (withUnsafePointer(&i) { UnsafePointer<T>($0).memory }).hashValue != 0 {
        i += 1
    }
    return i
}

斯威夫特3:

func enumCount<T: Hashable>(_: T.Type) -> Int {
   var i = 1
   while (withUnsafePointer(to: &i, {
      return $0.withMemoryRebound(to: T.self, capacity: 1, { return $0.pointee })
   }).hashValue != 0) {
      i += 1
   }
      return i
   }