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

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

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

结果示例:

♠
♥
♦
♣

当前回答

我使用计算属性,它返回所有值的数组(感谢这篇文章http://natecook.com/blog/2014/10/loopy-random-enum-ideas/)。但是,它也使用int原始值,但我不需要在单独的属性中重复枚举的所有成员。

Xcode 6.1在如何使用rawValue获取enum成员方面做了一点改变,所以我修正了listing。还修复了第一个rawValue错误的小错误。

enum ValidSuits: Int {
    case Clubs = 0, Spades, Hearts, Diamonds
    func description() -> String {
        switch self {
        case .Clubs:
            return "♣︎"
        case .Spades:
            return "♠︎"
        case .Diamonds:
            return "♦︎"
        case .Hearts:
            return "♥︎"
        }
    }

    static var allSuits: [ValidSuits] {
        return Array(
            SequenceOf {
                () -> GeneratorOf<ValidSuits> in
                var i=0
                return GeneratorOf<ValidSuits> {
                    return ValidSuits(rawValue: i++)
                }
            }
        )
    }
}

其他回答

在处理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
    }
}

您可以通过实现ForwardIndexType协议来迭代枚举。

ForwardIndexType协议要求您定义一个继任者()函数来逐级遍历元素。

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

    // ... other functions

    // Option 1 - Figure it out by hand
    func successor() -> Rank {
        switch self {
            case .Ace:
              return .Two
            case .Two:
              return .Three

            // ... etc.

            default:
              return .King
        }
    }

    // Option 2 - Define an operator!
    func successor() -> Rank {
        return self + 1
    }
}

// NOTE: The operator is defined OUTSIDE the class
func + (left: Rank, right: Int) -> Rank {
    // I'm using to/from raw here, but again, you can use a case statement
    // or whatever else you can think of

    return left == .King ? .King : Rank(rawValue: left.rawValue + right)!
}

在开或闭范围内迭代(..<或…)将在内部调用继任者()函数,允许你这样写:

// Under the covers, successor(Rank.King) and successor(Rank.Ace) are called to establish limits
for r in Rank.Ace...Rank.King {
    // Do something useful
}

在Swift 3中,当底层枚举有rawValue时,你可以实现Strideable协议。优点是不像其他建议那样创建值数组,并且标准的Swift“for in”循环工作,这是一个很好的语法。

// "Int" to get rawValue, and Strideable so we can iterate
enum MyColorEnum: Int, Strideable {
    case Red
    case Green
    case Blue
    case Black

    // required by Strideable
    typealias Stride = Int

    func advanced(by n:Stride) -> MyColorEnum {
        var next = self.rawValue + n
        if next > MyColorEnum.Black.rawValue {
            next = MyColorEnum.Black.rawValue
        }
        return MyColorEnum(rawValue: next)!
    }

    func distance(to other: MyColorEnum) -> Int {
        return other.rawValue - self.rawValue
    }

    // just for printing
    func simpleDescription() -> String {
        switch self {
        case .Red: return "Red"
        case .Green: return "Green"
        case .Blue: return "Blue"
        case .Black: return "Black"
        }
    }
}

// this is how you use it:
for i in MyColorEnum.Red ... MyColorEnum.Black {
    print("ENUM: \(i)")
}

编辑: 快速进化提案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)
}

对不起,我的回答是具体到我如何在我需要做的事情中使用这篇文章。对于那些无意中遇到这个问题的人,寻找一种方法在枚举中找到一个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示例代码包含了完全相同的技术。

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