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

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

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

结果示例:

♠
♥
♦
♣

当前回答

其他的解决方法都是可行的,但它们都假设了可能的等级和花色的数量,或者第一和最后的等级是什么。的确,在可预见的未来,一副纸牌的布局可能不会有太大变化。然而,一般来说,编写尽可能少假设的代码会更简洁。我的解决方案:

我已经在Suit枚举中添加了一个原始类型,所以我可以使用Suit(rawValue:)来访问Suit案例:

enum Suit: Int {
    case Spades = 1
    case Hearts, Diamonds, Clubs
    func simpleDescription() -> String {
        switch self {
            case .Spades:
                return "spades"
            case .Hearts:
                return "hearts"
            case .Diamonds:
                return "diamonds"
            case .Clubs:
                return "clubs"
        }
    }
    func color() -> String {
        switch self {
        case .Spades:
            return "black"
        case .Clubs:
            return "black"
        case .Diamonds:
            return "red"
        case .Hearts:
            return "red"
        }
    }
}

enum Rank: Int {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King
    func simpleDescription() -> String {
        switch self {
            case .Ace:
                return "ace"
            case .Jack:
                return "jack"
            case .Queen:
                return "queen"
            case .King:
                return "king"
            default:
                return String(self.rawValue)
        }
    }
}

在Card的createDeck()方法实现的下面。init(rawValue:)是一个可失败的初始化式,返回一个可选值。通过在两个while语句中展开并检查它的值,不需要假设Rank或Suit情况的数量:

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
    func createDeck() -> [Card] {
        var n = 1
        var deck = [Card]()
        while let rank = Rank(rawValue: n) {
            var m = 1
            while let suit = Suit(rawValue: m) {
                deck.append(Card(rank: rank, suit: suit))
                m += 1
            }
            n += 1
        }
        return deck
    }
}

下面是如何调用createDeck方法:

let card = Card(rank: Rank.Ace, suit: Suit.Clubs)
let deck = card.createDeck()

其他回答

更新到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
        }
    }
}

与@Kametrixom的答案在这里,我相信返回一个数组将比返回AnySequence更好,因为你可以访问所有数组的好东西,如计数等。

以下是改写后的内容:

public protocol EnumCollection : Hashable {}
extension EnumCollection {
    public static func allValues() -> [Self] {
        typealias S = Self
        let retVal = AnySequence { () -> AnyGenerator<S> in
            var raw = 0
            return AnyGenerator {
                let current : Self = withUnsafePointer(&raw) { UnsafePointer($0).memory }
                guard current.hashValue == raw else { return nil }
                raw += 1
                return current
            }
        }

        return [S](retVal)
    }
}

它花了我一点,而不仅仅是一个方法在结构像swift书调用,但我在枚举中设置了下一个函数。我会使用一个协议,我不知道为什么,但有秩设置为int混乱。

enum Rank: Int {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King
    func simpleDescription() -> String {
        switch self {
        case .Ace:
            return "ace"
        case .Jack:
            return "jack"
        case .Queen:
            return "Queen"
        case .King:
            return "King"
        default:
            return String(self.toRaw())
        }
    }
    mutating func next() -> Rank {
        var rank = self
        var rawrank = rank.toRaw()
        var nrank: Rank = self
        rawrank = rawrank + 1
        if let newRank = Rank.fromRaw(rawrank) {
            println("\(newRank.simpleDescription())")
            nrank = newRank
        } else {
            return self
        }
        return nrank
    }
}

enum Suit {
    case Spades, Hearts, Diamonds, Clubs
    func color() -> String {
        switch self {
        case .Spades, .Clubs:
            return "black"
        default:
            return "red"
        }
    }
    func simpleDescription() -> String {
        switch self {
        case .Spades:
            return "spades"
        case .Hearts:
            return "hearts"
        case .Diamonds:
            return "diamonds"
        case .Clubs:
            return "clubs"
        }
    }
    mutating func next() -> Suit {
        switch self {
        case .Spades:
            return Hearts
        case .Hearts:
            return Diamonds
        case .Diamonds:
            return Clubs
        case .Clubs:
            return Spades
        }
    }
}

struct Card {
    var rank: Rank
    var suit: Suit
    func deck() -> Card[] {
        var tRank = self.rank
        var tSuit = self.suit
        let tcards = 52 // we start from 0
        var cards: Card[] = []
        for i in 0..tcards {
            var card = Card(rank: tRank, suit: tSuit)
            cards.append(card)
            tRank = tRank.next()
            tSuit = tSuit.next()
        }
        return cards
    }
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
}

var card = Card(rank: .Ace, suit: .Spades)
var deck = card.deck()

我使用了一些常识,但这可以通过将花色乘以等级来轻松纠正(如果你没有使用标准的桥牌,你必须相应地改变枚举,如果基本上只是通过不同的枚举进行步骤)。为了节省时间,我使用了ranks rawValues,如果你愿意,你也可以为西装做同样的事情。然而,这个例子没有它,所以我决定在不改变suit rawValue的情况下找出它

这是一个相当老的帖子,来自Swift 2.0。现在有一些更好的解决方案,使用了swift 3.0的新特性: 在Swift 3.0中迭代一个Enum

关于这个问题,有一个解决方案,它使用了Swift 4.2的一个新功能(在我写这篇编辑时还没有发布): 我如何得到一个Swift枚举的计数?


在这个帖子中有很多好的解决方案,但其中一些非常复杂。我喜欢尽可能地简化。这里有一个解决方案,可能适用于不同的需求,但我认为它在大多数情况下都很好:

enum Number: String {
    case One
    case Two
    case Three
    case Four
    case EndIndex

    func nextCase () -> Number
    {
        switch self {
        case .One:
            return .Two
        case .Two:
            return .Three
        case .Three:
            return .Four
        case .Four:
            return .EndIndex

        /* 
        Add all additional cases above
        */
        case .EndIndex:
            return .EndIndex
        }
    }

    static var allValues: [String] {
        var array: [String] = Array()
        var number = Number.One

        while number != Number.EndIndex {
            array.append(number.rawValue)
            number = number.nextCase()
        }
        return array
    }
}

迭代:

for item in Number.allValues {
    print("number is: \(item)")
}

我使用了下面的方法,假设我知道哪个是Rank enum中的最后一个值,所有的Rank在Ace之后都有增量值

我喜欢这种方式,因为它干净,小,容易理解

 func cardDeck() -> Card[] {
     var cards: Card[] = []
     let minRank = Rank.Ace.toRaw()
     let maxRank = Rank.King.toRaw()

     for rank in minRank...maxRank {
         if var convertedRank: Rank = Rank.fromRaw(rank) {
             cards.append(Card(rank: convertedRank, suite: Suite.Clubs))
             cards.append(Card(rank: convertedRank, suite: Suite.Diamonds))
             cards.append(Card(rank: convertedRank, suite: Suite.Hearts))
             cards.append(Card(rank: convertedRank, suite: Suite.Spades))
         }
    }

    return cards
}