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

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

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

结果示例:

♠
♥
♦
♣

当前回答

下面是我用来迭代枚举和从一个枚举提供多个值类型的方法

enum IterateEnum: Int {
    case Zero
    case One
    case Two
    case Three
    case Four
    case Five
    case Six
    case Seven

    //tuple allows multiple values to be derived from the enum case, and
    //since it is using a switch with no default, if a new case is added,
    //a compiler error will be returned if it doesn't have a value tuple set
    var value: (french: String, spanish: String, japanese: String) {
        switch self {
        case .Zero: return (french: "zéro", spanish: "cero", japanese: "nuru")
        case .One: return (french: "un", spanish: "uno", japanese: "ichi")
        case .Two: return (french: "deux", spanish: "dos", japanese: "ni")
        case .Three: return (french: "trois", spanish: "tres", japanese: "san")
        case .Four: return (french: "quatre", spanish: "cuatro", japanese: "shi")
        case .Five: return (french: "cinq", spanish: "cinco", japanese: "go")
        case .Six: return (french: "six", spanish: "seis", japanese: "roku")
        case .Seven: return (french: "sept", spanish: "siete", japanese: "shichi")
        }
    }

    //Used to iterate enum or otherwise access enum case by index order.
    //Iterate by looping until it returns nil
    static func item(index: Int) -> IterateEnum? {
        return IterateEnum.init(rawValue: index)
    }

    static func numberFromSpanish(number: String) -> IterateEnum? {
        return findItem { $0.value.spanish == number }
    }

    //use block to test value property to retrieve the enum case        
    static func findItem(predicate: ((_: IterateEnum) -> Bool)) -> IterateEnum? {

        var enumIndex: Int = -1
        var enumCase: IterateEnum?

        //Iterate until item returns nil
        repeat {
            enumIndex += 1
            enumCase = IterateEnum.item(index: enumIndex)

            if let eCase = enumCase {

                if predicate(eCase) {
                    return eCase
                }
            }
        } while enumCase != nil
        return nil
    }
}

var enumIndex: Int = -1
var enumCase: IterateEnum?

// Iterate until item returns nil
repeat {
    enumIndex += 1
    enumCase = IterateEnum.item(index: enumIndex)
    if let eCase = enumCase {
        print("The number \(eCase) in french: \(eCase.value.french), spanish: \(eCase.value.spanish), japanese: \(eCase.value.japanese)")
    }
} while enumCase != nil

print("Total of \(enumIndex) cases")

let number = IterateEnum.numberFromSpanish(number: "siete")

print("siete in japanese: \((number?.value.japanese ?? "Unknown"))")

输出如下:

法语中的数字Zero: zéro,西班牙语中的数字cero,日语中的数字nuru 数字一在法语中是un,西班牙语中是uno,日语中是ichi 法语中的数字2是deux,西班牙语中的数字2是dos,日语中的数字2是ni 法语中的“三”是“trois”,西班牙语中的“tres”,日语中的“san” 法语中的“四”是quatre,西班牙语中的“四”是cuatro,日语中的“四”是shi 数字五在法语中是cinq,西班牙语中是cinco,日语中是go 数字6在法语中是Six,西班牙语是seis,日语是roku 法语中的数字“七”是“sept”,西班牙语中的“siete”,日语中的“shichi”

共8例

Siete在日语中的意思是:shichi


更新

我最近创建了一个协议来处理枚举。该协议需要一个Int原始值的enum:

protocol EnumIteration {

    //Used to iterate enum or otherwise access enum case by index order. Iterate by looping until it returns nil

    static func item(index:Int) -> Self?
    static func iterate(item:((index:Int, enumCase:Self)->()), completion:(()->())?) {
    static func findItem(predicate:((enumCase:Self)->Bool)) -> Self?
    static func count() -> Int
}

extension EnumIteration where Self: RawRepresentable, Self.RawValue == Int {

    //Used to iterate enum or otherwise access enum case by index order. Iterate by looping until it returns nil
    static func item(index:Int) -> Self? {
        return Self.init(rawValue: index)
    }

    static func iterate(item:((index:Int, enumCase:Self)->()), completion:(()->())?) {

        var enumIndex:Int = -1
        var enumCase:Self?

        //Iterate until item returns nil
        repeat {
            enumIndex += 1
            enumCase = Self.item(enumIndex)

            if let eCase = enumCase {
                item(index: enumIndex, enumCase: eCase)
            }
        } while enumCase != nil
        completion?()
    }

    static func findItem(predicate:((enumCase:Self)->Bool)) -> Self? {

        var enumIndex:Int = -1
        var enumCase:Self?

        //Iterate until item returns nil
        repeat {
            enumIndex += 1
            enumCase = Self.item(enumIndex)

            if let eCase = enumCase {

                if predicate(enumCase:eCase) {
                    return eCase
                }
            }
        } while enumCase != nil
        return nil
    }

    static func count() -> Int {
        var enumIndex:Int = -1
        var enumCase:Self?

        //Iterate until item returns nil
        repeat {
            enumIndex += 1
            enumCase = Self.item(enumIndex)
        } while enumCase != nil

        //last enumIndex (when enumCase == nil) is equal to the enum count
        return enumIndex
    }
}

其他回答

我发现了一种有点俗气但更安全的方法,它不需要键入两次值或引用枚举值的内存,因此不太可能损坏。

基本上,与其使用枚举,不如创建一个具有单个实例的结构体,并将所有enum-values设置为常量。然后可以使用Mirror查询变量

public struct Suit{

    // the values
    let spades = "♠"
    let hearts = "♥"
    let diamonds = "♦"
    let clubs = "♣"

    // make a single instance of the Suit struct, Suit.instance
    struct SStruct{static var instance: Suit = Suit()}
    static var instance : Suit{
        get{return SStruct.instance}
        set{SStruct.instance = newValue}
    }

    // an array with all of the raw values
    static var allValues: [String]{
        var values = [String]()

        let mirror = Mirror(reflecting: Suit.instance)
        for (_, v) in mirror.children{
            guard let suit = v as? String else{continue}
            values.append(suit)
        }

        return values
    }
}

如果使用此方法,则需要使用Suit.instance.clubs或Suit.instance.spades来获取单个值

但所有这些都太无聊了……让我们做一些事情,使它更像一个真正的enum!

public struct SuitType{

    // store multiple things for each suit
    let spades = Suit("♠", order: 4)
    let hearts = Suit("♥", order: 3)
    let diamonds = Suit("♦", order: 2)
    let clubs = Suit("♣", order: 1)

    struct SStruct{static var instance: SuitType = SuitType()}
    static var instance : SuitType{
        get{return SStruct.instance}
        set{SStruct.instance = newValue}
    }

    // a dictionary mapping the raw values to the values
    static var allValuesDictionary: [String : Suit]{
        var values = [String : Suit]()

        let mirror = Mirror(reflecting: SuitType.instance)
        for (_, v) in mirror.children{
            guard let suit = v as? Suit else{continue}
            values[suit.rawValue] = suit
        }

        return values
    }
}

public struct Suit: RawRepresentable, Hashable{
    public var rawValue: String
    public typealias RawValue = String

    public var hashValue: Int{
        // find some integer that can be used to uniquely identify
        // each value. In this case, we could have used the order
        // variable because it is a unique value, yet to make this
        // apply to more cases, the hash table address of rawValue
        // will be returned, which should work in almost all cases
        // 
        // you could also add a hashValue parameter to init() and
        // give each suit a different hash value
        return rawValue.hash
    }

    public var order: Int
    public init(_ value: String, order: Int){
        self.rawValue = value
        self.order = order
    }

    // an array of all of the Suit values
    static var allValues: [Suit]{
        var values = [Suit]()

        let mirror = Mirror(reflecting: SuitType.instance)
        for (_, v) in mirror.children{
            guard let suit = v as? Suit else{continue}
            values.append(suit)
        }

        return values
    }

    // allows for using Suit(rawValue: "♦"), like a normal enum
    public init?(rawValue: String){
        // get the Suit from allValuesDictionary in SuitType, or return nil if that raw value doesn't exist
        guard let suit = SuitType.allValuesDictionary[rawValue] else{return nil}
        // initialize a new Suit with the same properties as that with the same raw value
        self.init(suit.rawValue, order: suit.order)
    }
}

你现在可以做

let allSuits: [Suit] = Suit.allValues

or

for suit in Suit.allValues{
   print("The suit \(suit.rawValue) has the order \(suit.order)")
}

然而,要获得一个单一,你仍然需要使用SuitType.instance.spades或SuitType.instance.hearts。为了更加直观,您可以向Suit添加一些允许您使用Suit.type的代码。*而不是SuitType.instance.*

public struct Suit: RawRepresentable, Hashable{
   // ...your code...

   static var type = SuitType.instance

   // ...more of your code...
}

您现在可以使用Suit.type.diamonds而不是SuitType.instance。diamonds,或者Suit.type.clubs而不是SuitType.instance.clubs

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())
        }
    }
}

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, .Clubs: return "black"
        case .Hearts, .Diamonds: return "red"
        }
    }
}

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }

    static func createPokers() -> Card[] {
        let ranks = Array(Rank.Ace.toRaw()...Rank.King.toRaw())
        let suits = Array(Suit.Spades.toRaw()...Suit.Clubs.toRaw())
        let cards = suits.reduce(Card[]()) { (tempCards, suit) in
            tempCards + ranks.map { rank in
                Card(rank: Rank.fromRaw(rank)!, suit: Suit.fromRaw(suit)!)
            }
        }
        return cards
    }
}

这是一个相当老的帖子,来自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)")
}

在Swift中,枚举类型可以像EnumType一样访问。案例:

let tableView = UITableView(frame: self.view. view)UITableViewStyle.Plain)

大多数情况下,只有当您有几个选项可以使用,并且确切地知道在每个选项上要做什么时,才会使用枚举类型。

在处理枚举类型时,使用for-in结构没有太大意义。

你可以这样做,例如:

func sumNumbers(numbers : Int...) -> Int {
    var sum = 0

    for number in numbers{
        sum += number
    }

    return sum
}
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
    }
}

这个怎么样?