ios 如何将所有枚举值作为数组获取

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32952248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 07:54:49  来源:igfitidea点击:

How to get all enum values as an array

iosarraysswiftenums

提问by Isuru

I have the following enum.

我有以下枚举。

enum EstimateItemStatus: Printable {
    case Pending
    case OnHold
    case Done

    var description: String {
        switch self {
        case .Pending: return "Pending"
        case .OnHold: return "On Hold"
        case .Done: return "Done"
        }
    }

    init?(id : Int) {
        switch id {
        case 1:
            self = .Pending
        case 2:
            self = .OnHold
        case 3:
            self = .Done
        default:
            return nil
        }
    }
}

I need to get all the raw values as an array of strings (like so ["Pending", "On Hold", "Done"]).

我需要将所有原始值作为字符串数组获取(像这样["Pending", "On Hold", "Done"])。

I added this method to the enum.

我将此方法添加到枚举中。

func toArray() -> [String] {
    var n = 1
    return Array(
        GeneratorOf<EstimateItemStatus> {
            return EstimateItemStatus(id: n++)!.description
        }
    )
}

But I'm getting the following error.

但我收到以下错误。

Cannot find an initializer for type 'GeneratorOf' that accepts an argument list of type '(() -> _)'

无法找到接受类型为“(() -> _)”的参数列表的“GeneratorOf”类型的初始值设定项

Is there is an easier, better or more elegant way to do this?

有没有更简单、更好或更优雅的方法来做到这一点?

回答by Code Different

For Swift 4.2 (Xcode 10) and later

对于 Swift 4.2 (Xcode 10) 及更高版本

There's a CaseIterableprotocol:

有一个CaseIterable协议:

enum EstimateItemStatus: String, CaseIterable {
    case pending = "Pending"
    case onHold = "OnHold"
    case done = "Done"

    init?(id : Int) {
        switch id {
        case 1: self = .pending
        case 2: self = .onHold
        case 3: self = .done
        default: return nil
        }
    }
}

for value in EstimateItemStatus.allCases {
    print(value)
}


For Swift < 4.2

对于 Swift < 4.2

No, you can't query an enumfor what values it contains. See this article. You have to define an array that list all the values you have. Also check out Frank Valbuena's solution in "How to get all enum values as an array".

不,您不能查询enum它包含的值。请参阅这篇文章。您必须定义一个数组,列出您拥有的所有值。另请查看“如何将所有枚举值作为数组获取”中的 Frank Valbuena 解决方案。

enum EstimateItemStatus: String {
    case Pending = "Pending"
    case OnHold = "OnHold"
    case Done = "Done"

    static let allValues = [Pending, OnHold, Done]

    init?(id : Int) {
        switch id {
        case 1:
            self = .Pending
        case 2:
            self = .OnHold
        case 3:
            self = .Done
        default:
            return nil
        }
    }
}

for value in EstimateItemStatus.allValues {
    print(value)
}

回答by Sh_Khan

Swift 4.2introduces a new protocol named CaseIterable

Swift 4.2引入了一个名为的新协议CaseIterable

enum Fruit : CaseIterable {
    case apple , apricot , orange, lemon
}

that when you conforms to , you can get an array from the enumcases like this

当你符合时,你可以从这样的enum情况中得到一个数组

for fruit in Fruit.allCases {
    print("I like eating \(fruit).")
}

回答by maxwell

Add CaseIterableprotocol to enum:

CaseIterable协议添加到枚举:

enum EstimateItemStatus: String, CaseIterable {
    case pending = "Pending"
    case onHold = "OnHold"
    case done = "Done"
}

Usage:

用法:

let values: [String] = EstimateItemStatus.allCases.map { 
enum MyEnum {
    case case1
    case case2
    case case3
}

extension MyEnum {
    static var allValues: [MyEnum] {
        var allValues: [MyEnum] = []
        switch (MyEnum.case1) {
        case .case1: allValues.append(.case1); fallthrough
        case .case2: allValues.append(.case2); fallthrough
        case .case3: allValues.append(.case3)
        }
        return allValues
    }
}
.rawValue } //["Pending", "OnHold", "Done"]

回答by Frank Valbuena

There's another way that at least is safe at compile time:

还有另一种方法至少在编译时是安全的:

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) { 
enum YourEnum: EnumCollection { //code }

YourEnum.cases()
.withMemoryRebound(to: S.self, capacity: 1) {
EnumName.allCases.map{
enum EstimateItemStatus: String, CaseIterable {
  case pending = "Pending"
  case onHold = "OnHold"
  case done = "Done"

  static var statusList: [String] {
    return EstimateItemStatus.allCases.map { 
protocol EnumSequenceElement: Strideable {
    var rawValue: Int { get }
    init?(rawValue: Int)
}

extension EnumSequenceElement {
    func distance(to other: Self) -> Int {
        return other.rawValue - rawValue
    }

    func advanced(by n: Int) -> Self {
        return Self(rawValue: n + rawValue) ?? self
    }
}

struct EnumSequence<T: EnumSequenceElement>: Sequence, IteratorProtocol {
    typealias Element = T

    var current: Element? = T.init(rawValue: 0)

    mutating func next() -> Element? {
        defer {
            if let current = current {
                self.current = T.init(rawValue: current.rawValue + 1)
            }
        }
        return current
    }
}
.rawValue } } }
.rawValue}
.pointee } } guard current.hashValue == raw else { return nil } raw += 1 return current } } } }

Notice that this works for any enum type (RawRepresentable or not) and also if you add a new case then you will get a compiler error which is good since will force you to have this up to date.

请注意,这适用于任何枚举类型(RawRepresentable 与否),并且如果您添加一个新案例,那么您将收到一个编译器错误,这很好,因为这将迫使您将其更新。

回答by Daniel Kuta

I found somewhere this code:

我在某处找到了这个代码:

enum EstimateItemStatus: Int, EnumSequenceElement, CustomStringConvertible {
    case Pending
    case OnHold
    case Done

    var description: String {
        switch self {
        case .Pending:
            return "Pending"
        case .OnHold:
            return "On Hold"
        case .Done:
            return "Done"
        }
    }
}

for status in EnumSequence<EstimateItemStatus>() {
    print(status)
}
// Or by countable range iteration
for status: EstimateItemStatus in .Pending ... .Done {
    print(status)
}

Use:

用:

Pending
On Hold
Done

return list of cases from YourEnum

从 YourEnum 返回案例列表

回答by u2041954

To get a list for functional purposes, use the expression EnumName.allCaseswhich returns an array e.g.

要获取用于功能目的的列表,请使用EnumName.allCases返回数组的表达式,例如

enum Status: Int{
    case a
    case b
    case c

}

extension RawRepresentable where Self.RawValue == Int {

    static var values: [Self] {
        var values: [Self] = []
        var index = 1
        while let element = self.init(rawValue: index) {
            values.append(element)
            index += 1
        }
        return values
    }
}


Status.values.forEach { (st) in
    print(st)
}

will give you a list of Strings given that EnumName: String, CaseIterable

会给你一个字符串列表,因为 EnumName: String, CaseIterable

Note: use allCasesinstead of AllCases().

注意:使用allCases代替AllCases().

回答by Vladimir Pchelyakov

enum EstimateItemStatus: CaseIterable {
    case Pending
    case OnHold
    case Done

    var description: String {
        switch self {
        case .Pending: return "Pending"
        case .OnHold: return "On Hold"
        case .Done: return "Done"
        }
    }

    init?(id : Int) {
        switch id {
        case 1:
            self = .Pending
        case 2:
            self = .OnHold
        case 3:
            self = .Done
        default:
            return nil
        }
    }
}

["Pending", "OnHold", "Done"]

[“待定”、“暂停”、“完成”]

回答by mclam

After inspiration from Sequenceand hours of try n errors. I finally got this comfortable and beautiful Swift 4 way on Xcode 9.1:

在从Sequence和数小时的尝试错误中获得灵感之后。我终于在 Xcode 9.1 上获得了这个舒适而漂亮的 Swift 4 方式:

var myEnumArray = EstimateItemStatus.allCases

Usage:

用法:

##代码##

Output:

输出:

##代码##

回答by Carlos Chaguendo

You Can Use

您可以使用

##代码##

回答by Christopher Larsen

Update for Swift 5

Swift 5 更新

Easiest solution I've found is to use .allCaseson an enum that extends CaseIterable

我发现的最简单的解决方案是.allCases在扩展的枚举上使用CaseIterable

##代码##

.allCaseson any CaseIterableenum will return a Collectionof that element.

.allCases在任何CaseIterable枚举上将返回Collection该元素的一个。

##代码##

more info about CaseIterable

有关CaseIterable 的更多信息