Consider if there is a enum type of poker suit and rank. We want to enumerate both to get a whole set of poker.

The suit and rank are defined as below respectively:

enum Suit: String {
    case Spades = "Spades"
    case Hearts = "Hearts"
    case Clubs = "Clubs"
    case Diamonds = "Diamonds"

enum Rank: Int, Printable {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King
    var description: String {
        switch self {
        case .Ace:
            return "A"
        case .Jack:
            return "J"
        case .Queen:
            return "Q"
        case .King:
            return "K"
            return String(self.rawValue)

The most easy way should be looping in the two enum: first get a possible Suit enum value, and then loop in Rank to generate 13 cards.

In some other language, we could enumerate an enum type directly, or there might be a values property in the type for us to loop. The code might be like this:

for suit in Suit.values {
    for rank in Rank.values {
        // ...

However, it does not apply in Swift. The reason is in Swift enum, we can contain some extra data (the case Some(T)). It cannot be expressed in a statement without losing type information. In the example case, there is no such enum item with parameter, so we can construct a enumerable enum by using static property.

Create a protocol for it first:

protocol EnumeratableEnumType {
    static var allValues: [Self] {get}

And make Suit and Rank conform this protocol:

enum Suit: String, EnumeratableEnumType {


    static var allValues: [Suit] {
        return [.Spades, .Hearts, .Clubs, .Diamonds]

enum Rank: Int, Printable, EnumeratableEnumType {


    static var allValues: [Rank] {
        return [.Ace, .Two, .Three,
            .Four, .Five, .Six,
            .Seven, .Eight, .Nine,
            .Ten, .Jack, .Queen, .King]

After the allValues property implemented, we could follow our first idea:

for suit in Suit.allValues {
    for rank in Rank.allValues {
        print("\(suit.rawValue) \(rank)")

// Output
// Spades A
// Spades 2
// Spades 3
// ...
// Diamonds K