I have the following enum.
我有下面的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"]
).
我需要将所有原始值作为字符串数组(如so ["Pending"、"On Hold"、"Done")获取。
I added this method to the enum.
我将此方法添加到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'的初始化器,该初始化器接受类型'()-> _)'的参数列表
I can't figure out how to resolve this. Any help? Or please tell me if there is an easier/better/more elegant way to do this.
我想不出怎么解决这个问题。任何帮助吗?或者请告诉我是否有更简单/更好/更优雅的方法来做这件事。
Thank you.
谢谢你!
9 个解决方案
#1
8
I found somewhere this code:
我在什么地方找到了这个密码:
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
}
}
}
}
Use:
使用:
enum YourEnum: EnumCollection { //code }
YourEnum.cases()
return list of cases from YourEnum
从YourEnum返回病例列表
#2
16
For Swift 4.2 (Xcode 10) and later
There's a CaseIterable
protocol:
有一个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
No, you can't query an enum
for what values it contains. See this article. You have to define an array that list all the values you have:
不,您不能查询枚举包含的值。看到这篇文章。你必须定义一个列有所有值的数组:
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)
}
#3
9
There's another way that at least is safe at compile time:
还有一种方法至少在编译时是安全的:
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
}
}
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.
请注意,这适用于任何enum类型(RawRepresentable或not),而且如果您添加一个新案例,那么您将会得到一个编译器错误,这很好,因为它将迫使您更新此内容。
#4
3
Swift 4.2 introduces 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 enum
cases like this
当你遵守时,你可以从enum实例中获得一个数组,就像这样
for fruit in Fruit.allCases {
print("I like eating \(fruit).")
}
#5
2
For Swift 2
斯威夫特2
// Found http://*.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))
}
To use it:
使用它:
arrayEnum(MyEnumClass.self)
#6
1
After inspiration from Sequence and hours of try n errors. I finally got this comfortable and beautiful Swift 4 way on Xcode 9.1:
从序列和数小时的尝试中获得灵感。我终于在Xcode 9.1上得到了这款舒适美丽的Swift 4方式:
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
}
}
Usage:
用法:
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)
}
Output:
输出:
Pending
On Hold
Done
#7
0
If your enum is incremental and associated with numbers, you can use range of numbers that you map to enum values, like so:
如果enum是递增的,并且与数字相关联,则可以使用映射到enum值的数字范围,如下所示:
// Swift 3
enum EstimateItemStatus: Int {
case pending = 1,
onHold
done
}
let estimateItemStatusValues: [EstimateItemStatus?] = (EstimateItemStatus.pending.rawValue...EstimateItemStatus.done.rawValue).map { EstimateItemStatus(rawValue: $0) }
This doesn't quite work with enums associated with strings or anything other than numbers, but it works great if that is the case!
这并不完全适用于与字符串或除数字之外的任何东西相关的枚举,但如果是这样的话,它将非常有效!
#8
0
Details
Xcode 9.1, Swift 4
Xcode 9.1,斯威夫特4
Solution
protocol EnumIterator {
static func getItem(at index: Int) -> Self?
}
extension Array where Element: EnumIterator {
static var all: [Element] {
var result = [Element]()
var index = 0
while true {
if let item = Element.getItem(at: index) {
result.append(item)
index += 1
} else {
break
}
}
return result
}
}
Usage
enum
枚举
enum Enum: EnumIterator {
case val1, val2, val3
static func getItem(at index: Int) -> Enum? {
switch index {
case 0: return .val1
case 1: return .val2
case 2: return .val3
default: return nil
}
}
}
Array with all enum values
具有所有枚举值的数组
let array = [Enum].all
Full sample
Do not forget to insert the solution code here
不要忘记在这里插入解决方案代码
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let array1 = [Enum].all
print("\(array1)")
let array2 = [StringEnum].all
print("\(array2)")
}
}
enum Enum: EnumIterator {
case val1, val2, val3
static func getItem(at index: Int) -> Enum? {
switch index {
case 0: return .val1
case 1: return .val2
case 2: return .val3
default: return nil
}
}
}
enum StringEnum: String, EnumIterator {
case str1="str1", str2="str2", str3="str3"
static func getItem(at index: Int) -> StringEnum? {
switch index {
case 0: return .str1
case 1: return .str2
case 2: return .str3
default: return nil
}
}
}
Results
#9
0
You Can Use
您可以使用
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)
}
#1
8
I found somewhere this code:
我在什么地方找到了这个密码:
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
}
}
}
}
Use:
使用:
enum YourEnum: EnumCollection { //code }
YourEnum.cases()
return list of cases from YourEnum
从YourEnum返回病例列表
#2
16
For Swift 4.2 (Xcode 10) and later
There's a CaseIterable
protocol:
有一个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
No, you can't query an enum
for what values it contains. See this article. You have to define an array that list all the values you have:
不,您不能查询枚举包含的值。看到这篇文章。你必须定义一个列有所有值的数组:
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)
}
#3
9
There's another way that at least is safe at compile time:
还有一种方法至少在编译时是安全的:
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
}
}
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.
请注意,这适用于任何enum类型(RawRepresentable或not),而且如果您添加一个新案例,那么您将会得到一个编译器错误,这很好,因为它将迫使您更新此内容。
#4
3
Swift 4.2 introduces 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 enum
cases like this
当你遵守时,你可以从enum实例中获得一个数组,就像这样
for fruit in Fruit.allCases {
print("I like eating \(fruit).")
}
#5
2
For Swift 2
斯威夫特2
// Found http://*.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))
}
To use it:
使用它:
arrayEnum(MyEnumClass.self)
#6
1
After inspiration from Sequence and hours of try n errors. I finally got this comfortable and beautiful Swift 4 way on Xcode 9.1:
从序列和数小时的尝试中获得灵感。我终于在Xcode 9.1上得到了这款舒适美丽的Swift 4方式:
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
}
}
Usage:
用法:
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)
}
Output:
输出:
Pending
On Hold
Done
#7
0
If your enum is incremental and associated with numbers, you can use range of numbers that you map to enum values, like so:
如果enum是递增的,并且与数字相关联,则可以使用映射到enum值的数字范围,如下所示:
// Swift 3
enum EstimateItemStatus: Int {
case pending = 1,
onHold
done
}
let estimateItemStatusValues: [EstimateItemStatus?] = (EstimateItemStatus.pending.rawValue...EstimateItemStatus.done.rawValue).map { EstimateItemStatus(rawValue: $0) }
This doesn't quite work with enums associated with strings or anything other than numbers, but it works great if that is the case!
这并不完全适用于与字符串或除数字之外的任何东西相关的枚举,但如果是这样的话,它将非常有效!
#8
0
Details
Xcode 9.1, Swift 4
Xcode 9.1,斯威夫特4
Solution
protocol EnumIterator {
static func getItem(at index: Int) -> Self?
}
extension Array where Element: EnumIterator {
static var all: [Element] {
var result = [Element]()
var index = 0
while true {
if let item = Element.getItem(at: index) {
result.append(item)
index += 1
} else {
break
}
}
return result
}
}
Usage
enum
枚举
enum Enum: EnumIterator {
case val1, val2, val3
static func getItem(at index: Int) -> Enum? {
switch index {
case 0: return .val1
case 1: return .val2
case 2: return .val3
default: return nil
}
}
}
Array with all enum values
具有所有枚举值的数组
let array = [Enum].all
Full sample
Do not forget to insert the solution code here
不要忘记在这里插入解决方案代码
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let array1 = [Enum].all
print("\(array1)")
let array2 = [StringEnum].all
print("\(array2)")
}
}
enum Enum: EnumIterator {
case val1, val2, val3
static func getItem(at index: Int) -> Enum? {
switch index {
case 0: return .val1
case 1: return .val2
case 2: return .val3
default: return nil
}
}
}
enum StringEnum: String, EnumIterator {
case str1="str1", str2="str2", str3="str3"
static func getItem(at index: Int) -> StringEnum? {
switch index {
case 0: return .str1
case 1: return .str2
case 2: return .str3
default: return nil
}
}
}
Results
#9
0
You Can Use
您可以使用
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)
}