Get all enum values as an array
我有以下枚举。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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 } } } |
我需要将所有原始值作为字符串数组(如
我将此方法添加到枚举中。
1 2 3 4 5 6 7 8 | func toArray() -> [String] { var n = 1 return Array( GeneratorOf<EstimateItemStatus> { return EstimateItemStatus(id: n++)!.description } ) } |
但我得到以下错误。
找不到类型"Generatorof"的初始值设定项,该类型接受类型"(()->"
我不知道怎么解决这个问题。有什么帮助吗?或者请告诉我有没有更容易/更好/更优雅的方法来做这件事。
谢谢您。
对于Swift 4.2(Xcode 10)及更高版本
有一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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) } |
斯威夫特<4.2
不,不能查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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) } |
Swift 4.2引入了一个名为
1 2 3 | enum Fruit : CaseIterable { case apple , apricot , orange, lemon } |
当您符合时,您可以从这样的
1 2 3 | for fruit in Fruit.allCases { print("I like eating \(fruit).") } |
还有另一种方法至少在编译时是安全的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 } } |
请注意,这适用于任何枚举类型(rawrepresentable或not),并且如果您添加了一个新的案例,那么您将得到一个很好的编译器错误,因为这将强制您更新它。
我在某个地方找到了这个密码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 } } } } |
用途:
1 2 3 | enum YourEnum: EnumCollection { //code } YourEnum.cases() |
返回您的案例列表
将casiterable协议添加到枚举:
1 2 3 4 5 | enum EstimateItemStatus: String, CaseIterable { case pending ="Pending" case onHold ="OnHold" case done ="Done" } |
用途:
1 2 | let values: [String] = EstimateItemStatus.allCases.map { $0.rawValue } //["Pending","OnHold","Done"] |
要获取用于函数目的的列表,请使用返回数组的表达式
1 | EnumName.allCases.map{$0.rawValue} |
会给你一个字符串列表
注:用
你可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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) } |
从一系列的尝试和几个小时的错误中获得灵感。我终于在Xcode 9.1上找到了这条舒适漂亮的四路快跑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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 } } |
用途:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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) } |
输出:
1 2 3 | Pending On Hold Done |
斯威夫特2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // Found http://stackoverflow.com/questions/24007461/how-to-enumerate-an-enum-with-string-type func iterateEnum<T where T: Hashable, T: RawRepresentable>(_: 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 } } } func arrayEnum<T where T: Hashable, T: RawRepresentable>(type: T.Type) -> [T]{ return Array(iterateEnum(type)) } |
使用它:
1 | arrayEnum(MyEnumClass.self) |
如果枚举是增量的并且与数字关联,则可以使用映射到枚举值的数字范围,如:
1 2 3 4 5 6 7 8 | // Swift 3 enum EstimateItemStatus: Int { case pending = 1, onHold done } let estimateItemStatusValues: [EstimateItemStatus?] = (EstimateItemStatus.pending.rawValue...EstimateItemStatus.done.rawValue).map { EstimateItemStatus(rawValue: $0) } |
这不太适用于与字符串或数字以外的任何事物相关联的枚举,但如果是这样的话,它会很好地工作!