如何枚举String类型的枚举?

Luc*_*ien 510 string enums enumerate swift

enum Suit: String {
    case spades = "?"
    case hearts = "?"
    case diamonds = "?"
    case clubs = "?"
}
Run Code Online (Sandbox Code Playgroud)

例如,我该怎么做:

for suit in Suit {
    // do something with suit
    print(suit.rawValue)
}
Run Code Online (Sandbox Code Playgroud)

结果示例:

?
?
?
?
Run Code Online (Sandbox Code Playgroud)

rou*_*ter 514

这篇文章与此相关https://www.swift-studies.com/blog/2014/6/10/enumerating-enums-in-swift

基本上提出的解决方案是

enum ProductCategory : String {
     case Washers = "washers", Dryers = "dryers", Toasters = "toasters"

     static let allValues = [Washers, Dryers, Toasters]
}

for category in ProductCategory.allValues{
     //Do something
}
Run Code Online (Sandbox Code Playgroud)

  • 很好,但是......你必须输入两次枚举的元素 - 一次用于枚举,一次用于allValues.并不像人们希望的那样优雅. (181认同)
  • 在Java中,编译器会为您执行此操作,也许Swift 2.0也会这样做.特别是在Java中,所有枚举都获得了一个描述(Java中的toString)方法,该方法将String作为案例名称(Washers,...),并自动创建一组案例.Java还为您提供位置索引.正如我所说,也许是Swift 2.0. (3认同)
  • 同意"但是"......但是正如文章中所述,或许有一个问题,即枚举实际上是一个集合,因此无序......请注意......定义的订单案例不会是一个糟糕的开始! (2认同)

rin*_*aro 275

我创建了一个实用函数iterateEnum()来迭代任意enum类型的case .

以下是示例用法:

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

for f in iterateEnum(Suit) {
    println(f.rawValue)
}
Run Code Online (Sandbox Code Playgroud)

输出:

?
?
?
?
Run Code Online (Sandbox Code Playgroud)

但是,这仅用于调试或测试目的:这依赖于几个未记录的当前(Swift1.1)编译器行为.所以,使用它需要你自担风险:)

这是代码:

func iterateEnum<T: Hashable>(_: T.Type) -> GeneratorOf<T> {
    var cast: (Int -> T)!
    switch sizeof(T) {
        case 0: return GeneratorOf(GeneratorOfOne(unsafeBitCast((), T.self)))
        case 1: cast = { unsafeBitCast(UInt8(truncatingBitPattern: $0), T.self) }
        case 2: cast = { unsafeBitCast(UInt16(truncatingBitPattern: $0), T.self) }
        case 4: cast = { unsafeBitCast(UInt32(truncatingBitPattern: $0), T.self) }
        case 8: cast = { unsafeBitCast(UInt64($0), T.self) }
        default: fatalError("cannot be here")
    }

    var i = 0
    return GeneratorOf {
        let next = cast(i)
        return next.hashValue == i++ ? next : nil
    }
}
Run Code Online (Sandbox Code Playgroud)

根本的想法是:

  • 内存表示enum- 不包括enum具有关联类型的s - 只是案例的索引,当案例的计数是2...256,它与UInt8,何时257...65536,UInt16等等时相同.因此,它可以unsafeBitcast来自相应的无符号整数类型.
  • .hashValue 枚举值的大小与大小写的索引相同.
  • .hashValue无效索引中获取的枚举值是0

添加:

修订了Swift2,并从@ Kametrixom的答案中实现了铸造思路

func iterateEnum<T: Hashable>(_: T.Type) -> AnyGenerator<T> {
    var i = 0
    return anyGenerator {
        let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
        return next.hashValue == i++ ? next : nil
    }
}
Run Code Online (Sandbox Code Playgroud)

增加: 修改为Swift3

func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
    var i = 0
    return AnyIterator {
        let next = withUnsafePointer(to: &i) {
            $0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee }
        }
        if next.hashValue != i { return nil }
        i += 1
        return next
    }
}
Run Code Online (Sandbox Code Playgroud)

增加: 针对Swift3.0.1进行了修订

func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
    var i = 0
    return AnyIterator {
        let next = withUnsafeBytes(of: &i) { $0.load(as: T.self) }
        if next.hashValue != i { return nil }
        i += 1
        return next
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 真棒,唯一回答这个问题的答案!但是......不会碰它!但努力+1! (20认同)
  • +1这非常棒.它也是,恕我直言,使用起来太聪明了,正如它在每个主要的Swift版本变化中显着突破所证明的那样.据作者所说,Swift 3版本是在Swift 3退出测试版之前的一个月完成的...如果你要接受这个答案并且学习所有这些`withUnsafePointer``withMemoryRebound`和`pointee`的东西,那么使用这一切都是这样的.否则,我会避免它. (16认同)
  • 我只是想添加这个现在已经在swift 4中打破了,但只在linux上,所以+1给上面的评论说这太聪明了. (5认同)
  • Swift 3版本效果很好.只需要稍微修改一下用法:对于f in iterateEnum(Suit.self){print(f.rawValue)} (2认同)

Cœu*_*œur 230

Swift 4.2+

Swift 4.2开始(使用Xcode 10),只需添加协议一致性即可CaseIterableallCases以下方面受益:

extension Suit: CaseIterable {}
Run Code Online (Sandbox Code Playgroud)

然后,这将打印所有可能的值:

Suit.allCases.forEach {
    print($0.rawValue)
}
Run Code Online (Sandbox Code Playgroud)

与早期Swift版本的兼容性(3.x和4.x)

只是模仿Swift 4.2的实现:

#if !swift(>=4.2)
public protocol CaseIterable {
    associatedtype AllCases: Collection where AllCases.Element == Self
    static var allCases: AllCases { get }
}
extension CaseIterable where Self: Hashable {
    static var allCases: [Self] {
        return [Self](AnySequence { () -> AnyIterator<Self> in
            var raw = 0
            var first: Self?
            return AnyIterator {
                let current = withUnsafeBytes(of: &raw) { $0.load(as: Self.self) }
                if raw == 0 {
                    first = current
                } else if current == first {
                    return nil
                }
                raw += 1
                return current
            }
        })
    }
}
#endif
Run Code Online (Sandbox Code Playgroud)

  • 看来您的版本比 CaseIterator 的内置版本有一个优点。我可以使用您的版本扩展在另一个文件中定义的枚举。如果将扩展中的 allCases 公开,您还可以扩展不同框架中定义的枚举。 (2认同)
  • @Cyber​​Mew 我已经更新了答案以澄清它。Swift 书籍和 Xcode 10 发行说明中提到的 CaseIterable 是在我的答案之后,他们使用了简化的示例,其中枚举没有“String”支持,这与当前的 Stack Overflow 问题相反。 (2认同)

sdd*_*sma 129

其他解决方案有效但它们都假设例如可能的等级和套装的数量,或者第一和最后等级可能是什么.诚然,在可预见的未来,一副牌的布局可能不会有太大变化.但是,一般来说,编写尽可能少的假设的代码更为简洁.我的解决方案

我已经在套装枚举中添加了原始类型,因此我可以使用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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

下面是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
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是调用createDeck方法的方法:

let card = Card(rank: Rank.Ace, suit: Suit.Clubs)
let deck = card.createDeck()
Run Code Online (Sandbox Code Playgroud)

  • 绝对最佳答案我在这个主题的各种主题上看到过.十分优雅.这适用于Int类型枚举,但我想知道如何迭代其他类型(字符串,自定义类型等). (12认同)
  • 这假设原始值是连续的.如果不是这样,例如当枚举表示位掩码标志时,循环过早退出. (10认同)
  • 这绝对是最好的解决方案.有一点需要注意.在本书的例子中,sdduursma没有"case Spades = 1".起初我没有抓住这个.这是一个选项,或者你可以只使用"var m = 0" (3认同)

Kam*_*xom 75

第二个答案确实有效

所以我在位和字节中偶然发现并创建了一个扩展(我后来发现它与@rintaro的答案非常相似).它可以像这样使用:

enum E : EnumCollection {
    case A, B, C
}

Array(E.cases())    // [A, B, C]
Run Code Online (Sandbox Code Playgroud)

值得注意的是它可以在任何枚举上使用(没有相关值).请注意,这不适用于没有案例的枚举.

放弃

@rintaro的回答一样,此代码使用枚举的基础表示.这种表示没有记录,将来可能会改变,这会破坏它 - >我不建议在生产中使用它.

代码(Swift 2.2,Xcode 7.3.1,不适用于Xcode 10)

protocol EnumCollection : Hashable {}
extension EnumCollection {
    static func cases() -> AnySequence<Self> {
        typealias S = Self
        return 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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

代码(Swift 3,Xcode 8.1,不适用于Xcode 10)

protocol EnumCollection : Hashable {}
extension EnumCollection {
    static func cases() -> AnySequence<Self> {
        typealias S = Self
        return AnySequence { () -> AnyIterator<S> in
            var raw = 0
            return AnyIterator {
                let current : Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee } }
                guard current.hashValue == raw else { return nil }
                raw += 1
                return current
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

(我不知道为什么我需要它typealias,但编译器抱怨没有它)

(我对这个答案进行了大的修改,看过去版本的编辑)

  • 这个答案甚至比我的回答更好,特别是在铸造部分:) (10认同)
  • Xcode 8 beta 6再次改变了这一点!我得到以下错误`'init'不可用:使用'withMemoryRebound(to:capacity:_)'临时查看内存作为另一种布局兼容类型. (5认同)

Rnd*_*Tsk 26

您可以通过实现ForwardIndexType协议来遍历枚举.

ForwardIndexType协议要求您定义一个successor()函数来逐步执行元素.

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)!
}
Run Code Online (Sandbox Code Playgroud)

在开放或闭合范围(..<...)上迭代将在内部调用successor()允许您编写此函数的函数:

// 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
}
Run Code Online (Sandbox Code Playgroud)

  • 我觉得这是对这个问题最"正确"的答案,即使是最"优雅"的(在这里可以考虑其他选项所需的额外代码)给定在一个范围内使用时产生的语法(语法就是我如果enumsratable sans workarounds枚举,我希望能够做到这一点.谢谢!虽然值得注意的是,如果操作员超载在其他地方使用除了后继()(这似乎很诱人),那么显然强制解包是危险的.中缀似乎没必要......? (2认同)

Dil*_*ari 19

更新代码:Swift 4.2/Swift 5

\n
enum Suit: String, CaseIterable {\n   case spades = "\xe2\x99\xa0"\n   case hearts = "\xe2\x99\xa5"\n   case diamonds = "\xe2\x99\xa6"\n   case clubs = "\xe2\x99\xa3"\n}\n
Run Code Online (Sandbox Code Playgroud)\n

要根据问题访问输出:

\n
for suitKey in Suit.allCases {\n    print(suitKey.rawValue)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

输出 :

\n
\xe2\x99\xa0\n\xe2\x99\xa5\n\xe2\x99\xa6\n\xe2\x99\xa3\n
Run Code Online (Sandbox Code Playgroud)\n

CaseIterable:提供其所有值的集合。\n符合 CaseIterable 协议的类型通常是没有关联值的枚举。使用 CaseIterable 类型时,可以使用 type\xe2\x80\x99s allCases 属性访问所有 type\xe2\x80\x99s 案例的集合。

\n

为了访问案例,我们使用.allCases。欲了解更多信息,请点击https://developer.apple.com/documentation/swift/caseiterable

\n


Alf*_*a07 17

原则上可以这样做,假设你没有为枚举的情况使用原始值赋值:

enum RankEnum: Int {
  case Ace
  case One
  case Two
}

class RankEnumGenerator: Generator {
    var i = 0
    typealias Element = RankEnum
    func next() -> Element? {
        let r = RankEnum.fromRaw(i)
        i += 1
        return r
    }
}

extension RankEnum {
    static func enumerate() -> SequenceOf<RankEnum> {
        return SequenceOf<RankEnum>({ RankEnumGenerator() })
    }
}

for r in RankEnum.enumerate() {
    println("\(r.toRaw())")
}
Run Code Online (Sandbox Code Playgroud)

  • 这很不错,但它仅适用于从0开始的连续Integer枚举 (7认同)

ada*_*com 17

这个问题现在变得容易多了.这是我的Swift 4.2解决方案.

enum Suit: Int, CaseIterable {
    case None
    case Spade, Heart, Diamond, Club

    static let allNonNullCases = Suit.allCases[Spade.rawValue...]
}

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

    static let allNonNullCases = Rank.allCases[Two.rawValue...]
}

func makeDeck(withJoker: Bool = false) -> [Card] {
    var deck = [Card]()
    for suit in Suit.allNonNullCases {
        for rank in Rank.allNonNullCases {
            deck.append(Card(suit: suit, rank: rank))
        }
    }
    if withJoker {
        deck.append(Card(suit: .None, rank: .Joker))
    }
    return deck
}
Run Code Online (Sandbox Code Playgroud)

前4.2

我喜欢这个在找到这个页面后放在一起的解决方案: Swift中的列表理解

它使用Int raws而不是Strings但它避免键入两次,它允许自定义范围,并且不硬编码原始值.

这是我原始解决方案的Swift 4版本,但请参见上面的4.2改进.

enum Suit: Int {
    case None
    case Spade, Heart, Diamond, Club

    static let allRawValues = Suit.Spade.rawValue...Suit.Club.rawValue
    static let allCases = Array(allRawValues.map{ Suit(rawValue: $0)! })
}
enum Rank: Int {
    case Joker
    case Two, Three, Four, Five, Six
    case Seven, Eight, Nine, Ten
    case Jack, Queen, King, Ace

    static let allRawValues = Rank.Two.rawValue...Rank.Ace.rawValue
    static let allCases = Array(allRawValues.map{ Rank(rawValue: $0)! })
}
func makeDeck(withJoker: Bool = false) -> [Card] {
    var deck = [Card]()
    for suit in Suit.allCases {
        for rank in Rank.allCases {
            deck.append(Card(suit: suit, rank: rank))
        }
    }
    if withJoker {
        deck.append(Card(suit: .None, rank: .Joker))
    }
    return deck
}
Run Code Online (Sandbox Code Playgroud)


Sen*_*ful 13

如果给enum 一个原始的Int值,它将使循环更容易.

例如,您可以使用anyGenerator获取可以枚举您的值的生成器:

enum Suit: Int, CustomStringConvertible {
    case Spades, Hearts, Diamonds, Clubs
    var description: String {
        switch self {
        case .Spades:   return "Spades"
        case .Hearts:   return "Hearts"
        case .Diamonds: return "Diamonds"
        case .Clubs:    return "Clubs"
        }
    }
    static func enumerate() -> AnyGenerator<Suit> {
        var nextIndex = Spades.rawValue
        return anyGenerator { Suit(rawValue: nextIndex++) }
    }
}
// You can now use it like this:
for suit in Suit.enumerate() {
    suit.description
}
// or like this:
let allSuits: [Suit] = Array(Suit.enumerate())
Run Code Online (Sandbox Code Playgroud)

然而,这看起来像一个相当常见的模式,如果我们可以通过简单地符合协议使任何枚举类型可枚举,那不是很好吗?好了Swift 2.0和协议扩展,现在我们可以!

只需将其添加到您的项目中:

protocol EnumerableEnum {
    init?(rawValue: Int)
    static func firstValue() -> Int
}
extension EnumerableEnum {
    static func enumerate() -> AnyGenerator<Self> {
        var nextIndex = firstRawValue()
        return anyGenerator { Self(rawValue: nextIndex++) }
    }
    static func firstRawValue() -> Int { return 0 }
}
Run Code Online (Sandbox Code Playgroud)

现在,只要您创建枚举(只要它具有Int原始值),您就可以通过符合协议使其可枚举:

enum Rank: Int, EnumerableEnum {
    case Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King
}
// ...
for rank in Rank.enumerate() { ... }
Run Code Online (Sandbox Code Playgroud)

如果您的枚举值不以0(默认值)开头,则覆盖该firstRawValue方法:

enum DeckColor: Int, EnumerableEnum {
    case Red = 10, Blue, Black
    static func firstRawValue() -> Int { return Red.rawValue }
}
// ...
let colors = Array(DeckColor.enumerate())
Run Code Online (Sandbox Code Playgroud)

最后西服类,包括更换simpleDescription更标准CustomStringConvertible协议,将是这样的:

enum Suit: Int, CustomStringConvertible, EnumerableEnum {
    case Spades, Hearts, Diamonds, Clubs
    var description: String {
        switch self {
        case .Spades:   return "Spades"
        case .Hearts:   return "Hearts"
        case .Diamonds: return "Diamonds"
        case .Clubs:    return "Clubs"
        }
    }
}
// ...
for suit in Suit.enumerate() {
    print(suit.description)
}
Run Code Online (Sandbox Code Playgroud)

编辑:

Swift 3 句法:

protocol EnumerableEnum {
    init?(rawValue: Int)
    static func firstRawValue() -> Int
}

extension EnumerableEnum {
    static func enumerate() -> AnyIterator<Self> {
        var nextIndex = firstRawValue()

        let iterator: AnyIterator<Self> = AnyIterator {
            defer { nextIndex = nextIndex + 1 }
            return Self(rawValue: nextIndex)
        }

        return iterator
    }

    static func firstRawValue() -> Int {
        return 0
    }
}
Run Code Online (Sandbox Code Playgroud)


ale*_*tro 12

更新为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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它的更新代码雨燕2.2的形式@ Kametrixom是一个 swer

适用于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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Joc*_*zer 12

斯威夫特 5 解决方案:

enum Suit: String, CaseIterable {
    case spades = "?"
    case hearts = "?"
    case diamonds = "?"
    case clubs = "?"
}

// access cases like this:

for suitKey in Suit.allCases {
    print(suitKey)
}
Run Code Online (Sandbox Code Playgroud)


Fab*_*llo 7

我发现自己在.allValues整个代码中都做了很多.我终于想出了一种简单地符合Iteratable协议并有rawValues()方法的方法.

protocol Iteratable {}
extension RawRepresentable where Self: RawRepresentable {

    static func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
        var i = 0
        return AnyIterator {
            let next = withUnsafePointer(to: &i) {
                $0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee }
            }
            if next.hashValue != i { return nil }
            i += 1
            return next
        }
    }
}

extension Iteratable where Self: RawRepresentable, Self: Hashable {
    static func hashValues() -> AnyIterator<Self> {
        return iterateEnum(self)
    }

    static func rawValues() -> [Self.RawValue] {
        return hashValues().map({$0.rawValue})
    }
}


// Example
enum Grocery: String, Iteratable {
    case Kroger = "kroger"
    case HEB = "h.e.b."
    case Randalls = "randalls"
}

let groceryHashes = Grocery.hashValues() // AnyIterator<Grocery>
let groceryRawValues = Grocery.rawValues() // ["kroger", "h.e.b.", "randalls"]
Run Code Online (Sandbox Code Playgroud)


War*_*shi 7

带有Swift 4.2的Xcode 10

enum Filter: String, CaseIterable {

    case salary = "Salary"
    case experience = "Experience"
    case technology = "Technology"
    case unutilized = "Unutilized"
    case unutilizedHV = "Unutilized High Value"

    static let allValues = Filter.allCases.map { $0.rawValue }
}
Run Code Online (Sandbox Code Playgroud)

称它为

print(Filter.allValues)
Run Code Online (Sandbox Code Playgroud)

印刷品:

[“工资”,“经验”,“技术”,“未利用”,“未利用的高价值”]


旧版本

为了enum代表Int

enum Filter: Int {
    case salary
    case experience
    case technology
    case unutilized
    case unutilizedHV

    static let allRawValues = salary.rawValue...unutilizedHV.rawValue  // First to last case
    static let allValues = allRawValues.map { Filter(rawValue: $0)!.rawValue }
}
Run Code Online (Sandbox Code Playgroud)

这样称呼它:

print(Filter.allValues)
Run Code Online (Sandbox Code Playgroud)

印刷品:

[0,1,2,3,4]


为了enum代表String

enum Filter: Int {
    case salary
    case experience
    case technology
    case unutilized
    case unutilizedHV

    static let allRawValues = salary.rawValue...unutilizedHV.rawValue  // First to last case
    static let allValues = allRawValues.map { Filter(rawValue: $0)!.description }
}

extension Filter: CustomStringConvertible {
    var description: String {
        switch self {
        case .salary: return "Salary"
        case .experience: return "Experience"
        case .technology: return "Technology"
        case .unutilized: return "Unutilized"
        case .unutilizedHV: return "Unutilized High Value"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

称它为

print(Filter.allValues)
Run Code Online (Sandbox Code Playgroud)

印刷品:

[“工资”,“经验”,“技术”,“未利用”,“未利用的高价值”]


ff1*_*f10 7

编辑: Swift进化提案 SE-0194衍生的Enum案例集提出了这个问题的一个解决方案.我们在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)
}
Run Code Online (Sandbox Code Playgroud)


Mos*_*ila 5

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
    }
}
Run Code Online (Sandbox Code Playgroud)

这个怎么样?


Kar*_*mar 5

你可以尝试这样枚举

enum Planet: String {
    case Mercury
    case Venus
    case Earth
    case Mars

    static var enumerate: [Planet] {
        var a: [Planet] = []
        switch Planet.Mercury {
            case .Mercury: a.append(.Mercury); fallthrough
            case .Venus: a.append(.Venus); fallthrough
            case .Earth: a.append(.Earth); fallthrough
            case .Mars: a.append(.Mars)
        }
    return a
    }
}

Planet.enumerate // [Mercury, Venus, Earth, Mars]
Run Code Online (Sandbox Code Playgroud)