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

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

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

结果示例:

♠
♥
♦
♣

当前回答

以下是我的建议。这不是完全令人满意的(我对Swift和OOP很陌生!),但也许有人可以改进它。这个想法是让每个枚举提供自己的范围信息作为.first和.last属性。它只向每个枚举添加了两行代码:仍然有点硬编码,但至少它没有复制整个集合。它确实需要将Suit enum修改为Int类型,就像Rank enum一样,而不是无类型的。

而不是重复整个解决方案,下面是我添加到。在case语句之后的某个地方(Suit enum类似):

var first: Int { return Ace.toRaw() }
var last: Int { return King.toRaw() }

以及我用来将deck构建为String数组的循环。(问题定义没有说明牌组是如何构造的。)

func createDeck() -> [String] {
    var deck: [String] = []
    var card: String
    for r in Rank.Ace.first...Rank.Ace.last {
        for s in Suit.Hearts.first...Suit.Hearts.last {
            card = Rank.simpleDescription( Rank.fromRaw(r)!)() + " of " + Suit.simpleDescription( Suit.fromRaw(s)!)()
           deck.append( card)
       }
    }
    return deck
}

这并不令人满意,因为属性与元素而不是enum相关联。但它确实为“for”循环增加了清晰度。我希望它是Rank。而不是Rank.Ace.first。它适用于任何元素,但很难看。有人能演示一下如何将其提升到enum级别吗?

为了使它工作,我从Card结构中提取了createDeck方法。我不知道如何从该结构返回一个[String]数组,这似乎是一个糟糕的地方,把这样的方法无论如何。

其他回答

在处理Swift 2.0时,以下是我的建议:

我已经将原始类型添加到Suit enum

enum Suit: Int {

然后:

struct Card {
    var rank: Rank
    var suit: Suit


    func fullDeck()-> [Card] {

        var deck = [Card]()

        for i in Rank.Ace.rawValue...Rank.King.rawValue {

            for j in Suit.Spades.rawValue...Suit.Clubs.rawValue {

                deck.append(Card(rank:Rank(rawValue: i)! , suit: Suit(rawValue: j)!))
            }
        }

        return deck
    }
}
enum Rank: Int
{
    case Ace = 0
    case Two, Three, Four, Five, Six, Seve, Eight, Nine, Ten
    case Jack, Queen, King
    case Count
}

enum Suit : Int
{
    case Spades = 0
    case Hearts, Diamonds, Clubs
    case Count
}

struct Card
{
    var rank:Rank
    var suit:Suit
}

class Test
{
    func makeDeck() -> Card[]
    {
        let suitsCount:Int = Suit.Count.toRaw()
        let rankCount:Int = Rank.Count.toRaw()
        let repeatedCard:Card = Card(rank:Rank.Ace, suit:Suit.Spades)
        let deck:Card[] = Card[](count:suitsCount*rankCount, repeatedValue:repeatedCard)

        for i:Int in 0..rankCount
        {
            for j:Int in 0..suitsCount
            {
                deck[i*suitsCount+j] = Card(rank: Rank.fromRaw(i)!, suit: Suit.fromRaw(j)!)
            }
        }
        return deck
    }
}

根据Rick的回答:这要快5倍

对不起,我的回答是具体到我如何在我需要做的事情中使用这篇文章。对于那些无意中遇到这个问题的人,寻找一种方法在枚举中找到一个case,这是一种方法(Swift 2新增):

编辑:小写驼峰现在是Swift 3 enum值的标准

// From apple docs: If the raw-value type is specified as String and you don’t assign values to the cases explicitly, each unassigned case is implicitly assigned a string with the same text as the name of that case.

enum Theme: String
    {
    case white, blue, green, lavender, grey
    }

func loadTheme(theme: String)
    {
    // this checks the string against the raw value of each enum case (note that the check could result in a nil value, since it's an optional, which is why we introduce the if/let block
    if let testTheme = Theme(rawValue: theme)
        {
        // testTheme is guaranteed to have an enum value at this point
        self.someOtherFunction(testTheme)
        }
    }

对于那些对枚举感到疑惑的人来说,本页上给出的答案包括一个包含所有枚举值的数组的静态var/let是正确的。最新的苹果tvOS示例代码包含了完全相同的技术。

也就是说,他们应该在语言中构建一个更方便的机制(苹果,你在听吗?)

(改进Karthik Kumar的回答)

这个解决方案是使用编译器来保证你不会错过一个case。

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

    static var enumerate: [Suit] {
        switch Suit.spades {
        // make sure the two lines are identical ^_^
        case        .spades, .hearts, .diamonds, .clubs:
            return [.spades, .hearts, .diamonds, .clubs]
        }
    }
}

枚举有toRaw()和fromRaw()方法。所以如果你的原始值是Int,你可以从第一个枚举迭代到最后一个枚举:

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"
        }
    }
}

for i in Suit.Spades.toRaw()...Suit.Clubs.toRaw() {
    if let covertedSuit = Suit.fromRaw(i) {
        let description = covertedSuit.simpleDescription()
    }
}

一个问题是在运行simpleDescription方法之前需要测试可选值,因此我们首先将convertedSuit设置为我们的值,然后将常量设置为convertedSuit.simpleDescription()