enum Suit: String {
    case spades = "♠"
    case hearts = "♥"
    case diamonds = "♦"
    case clubs = "♣"
}

例如,我怎么做这样的事情:

for suit in Suit {
    // do something with suit
    print(suit.rawValue)
}

结果示例:

♠
♥
♦
♣

当前回答

更新到Swift 2.2+

func iterateEnum<T: Hashable>(_: T.Type) -> AnyGenerator<T> {
    var i = 0
    return AnyGenerator {
        let next = withUnsafePointer(&i) {
            UnsafePointer<T>($0).memory
        }
        if next.hashValue == i {
            i += 1
            return next
        } else {
            return nil
        }
    }
}

它更新了Swift 2.2表单@Kametrixom的答案

Swift 3.0+(非常感谢@Philip)

func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
    var i = 0
    return AnyIterator {
        let next = withUnsafePointer(&i) {
            UnsafePointer<T>($0).pointee
        }
        if next.hashValue == i {
            i += 1
            return next
        } else {
            return nil
        }
    }
}

其他回答

编辑: 快速进化提案SE-0194枚举案例派生集合为这个问题提出了一个水平的解决方案。我们在Swift 4.2和更新版本中看到了它。该提案还指出了一些变通方法,这些方法与这里已经提到的一些方法类似,但可能会很有趣。

为了完整起见,我也会保留我原来的职位。


这是基于@Peymmankh的回答的另一种方法,适用于Swift 3。

public protocol EnumCollection: Hashable {}

extension EnumCollection {

public static func allValues() -> [Self] {
    typealias S = Self

    let retVal = AnySequence { () -> AnyIterator<S> in
        var raw = 0
        return AnyIterator {
            let current = withUnsafePointer(to: &raw) {
                 $0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee }
            }
            guard current.hashValue == raw else { return nil }
            raw += 1
            return current
        }
    }

    return [S](retVal)
}

有时,您可能会处理具有底层原始整数类型的枚举类型,这种类型在整个软件开发生命周期中都会发生变化。下面是一个很适合这种情况的例子:

public class MyClassThatLoadsTexturesEtc
{
    //...

    // Colors used for gems and sectors.
    public enum Color: Int
    {
        // Colors arranged in order of the spectrum.
        case First = 0
        case Red, Orange, Yellow, Green, Blue, Purple, Pink
        // --> Add more colors here, between the first and last markers.
        case Last
    }

    //...

    public func preloadGems()
    {
        // Preload all gems.
        for i in (Color.First.toRaw() + 1) ..< (Color.Last.toRaw())
        {
            let color = Color.fromRaw(i)!
            loadColoredTextures(forKey: color)
        }
    }

    //...
}

这个问题现在简单多了。以下是我的Swift 4.2解决方案:

enum Suit: Int, CaseIterable {
  case None
  case Spade, Heart, Diamond, Club

  static let allNonNullCases = Suit.allCases[Spade.rawValue...]
}

enum Rank: Int, CaseIterable {
  case Joker
  case Two, Three, Four, Five, Six, Seven, Eight
  case Nine, Ten, Jack, Queen, King, Ace

  static let allNonNullCases = Rank.allCases[Two.rawValue...]
}

func makeDeck(withJoker: Bool = false) -> [Card] {
  var deck = [Card]()
  for suit in Suit.allNonNullCases {
    for rank in Rank.allNonNullCases {
      deck.append(Card(suit: suit, rank: rank))
    }
  }
  if withJoker {
    deck.append(Card(suit: .None, rank: .Joker))
  }
  return deck
}

4。2:

我喜欢这个解决方案,我把找到“列表理解在Swift”。

它使用Int rawws而不是string,但它避免了键入两次,它允许自定义范围,并且不硬编码原始值。

这是我最初解决方案的Swift 4版本,但请参阅上面的4.2改进:

enum Suit: Int {
  case None
  case Spade, Heart, Diamond, Club

  static let allRawValues = Suit.Spade.rawValue...Suit.Club.rawValue
  static let allCases = Array(allRawValues.map{ Suit(rawValue: $0)! })
}
enum Rank: Int {
  case Joker
  case Two, Three, Four, Five, Six
  case Seven, Eight, Nine, Ten
  case Jack, Queen, King, Ace

  static let allRawValues = Rank.Two.rawValue...Rank.Ace.rawValue
  static let allCases = Array(allRawValues.map{ Rank(rawValue: $0)! })
}
func makeDeck(withJoker: Bool = false) -> [Card] {
  var deck = [Card]()
  for suit in Suit.allCases {
    for rank in Rank.allCases {
      deck.append(Card(suit: suit, rank: rank))
    }
  }
  if withJoker {
    deck.append(Card(suit: .None, rank: .Joker))
  }
  return deck
}
enum Rank: Int {
    ...
    static let ranks = (Rank.Ace.rawValue ... Rank.King.rawValue).map{Rank(rawValue: $0)! }

}
enum Suit {
    ...
    static let suits = [Spades, Hearts, Diamonds, Clubs]
}

struct Card {
    ...
    static func fullDesk() -> [Card] {
        var desk: [Card] = []
        for suit in Suit.suits {
            for rank in Rank.ranks {
                desk.append(Card(rank: rank,suit: suit))
            }
        }
        return desk
    }
}

这个怎么样?

我添加了函数count(),并迭代值:

public enum MetricType: Int {
    case mvps = 0
    case allNBA = 1
    case championshipRings = 2
    case finalAppearances = 3
    case gamesPlayed = 4
    case ppg = 5

    static func count() -> Int {
        return (ppg.rawValue) + 1
    }

    static var allValues: [MetricType] {
        var array: [MetricType] = Array()
        var item : MetricType = MetricType.mvps
        while item.rawValue < MetricType.count() {
            array.append(item)
            item = MetricType(rawValue: (item.rawValue + 1))!
        }
    return array
    }
}