I have a simple enum that I would like to iterate over. For this purpose, I\'ve adopted Sequence and IteratorProtocol as shown in the code below. BTW, this can be copy/paste
Iterated upon the solutions above, see below a protocol that can be implemented by enumerations to add the allValues sequence but also to allow the possibility to convert to and from string value.
Very convenient for String-like enumerations which need to support objective c (only int enumerations are allowed there).
public protocol ObjcEnumeration: LosslessStringConvertible, RawRepresentable where RawValue == Int {
static var allValues: AnySequence { get }
}
public extension ObjcEnumeration {
public static var allValues: AnySequence {
return AnySequence {
return IntegerEnumIterator()
}
}
public init?(_ description: String) {
guard let enumValue = Self.allValues.first(where: { $0.description == description }) else {
return nil
}
self.init(rawValue: enumValue.rawValue)
}
public var description: String {
return String(describing: self)
}
}
fileprivate struct IntegerEnumIterator: IteratorProtocol where T.RawValue == Int {
private var index = 0
mutating func next() -> T? {
defer {
index += 1
}
return T(rawValue: index)
}
}
For a concrete example:
@objc
enum Fruit: Int, ObjcEnumeration {
case apple, orange, pear
}
Now you can do:
for fruit in Fruit.allValues {
//Prints: "apple", "orange", "pear"
print("Fruit: \(fruit.description)")
if let otherFruit = Fruit(fruit.description), fruit == otherFruit {
print("Fruit could be constructed successfully from its description!")
}
}