Im trying to create an enum class with a type and a function that returns all the types.
Initially I have my enum in my object class and a function that returns these as an array:
class someClass: Mappable {
enum Type: Int {
case A = 0
case B = 1
case C = 2
}
}
}
func getAllTypes() -> [Type] {
return [Type.A, Type.B, Type.C]
}
}
The reason i want to extract this out of my object class is because this type is also used in other classes and i don't want to duplicate any unnecessary code.
I can manage to subclass the enum but not the function that returns all the types in an array.
Any help will be appreciated.
all using an executed-one-time-only closure and AnyGenerator@vacawama showed how to initialize the all array in a generalized manner using an executed-one-time-only closure in combination with the failable init(rawValue:) initialer of enum's. A slight variation of the method in the fore mentioned answer is to exchange the explicit while loop and array appending with an AnyGenerator:
enum Type: Int {
case A = 0, B, C, D, E, F, G, H
static let all: [Type] = {
var rValue = 0
return AnyGenerator<Type> {
defer { rValue += 1 }
return Type(rawValue: rValue)
}.map{$0}
}()
}
print(Type.all)
// [Type.A, Type.B, Type.C, Type.D, Type.E, Type.F, Type.G, Type.H]
This works under the condition that rawValue's are simply ++ increasing (0, 1, 2, ...).
all by conforming the enum to SequenceTypeAs another alternative, since your rawValue's are integer-wise sequential (++), you could let your enum conform to SequenceType, in which case the array of all cases can be easily generated simply by using .map
enum Type: Int, SequenceType {
case A = 0, B, C, D, E, F, G, H
init() { self = A } // Default (first) case intializer
/* conform Type to SequenceType (here: enables only
simple (self.rawValue)...last traversing) */
func generate() -> AnyGenerator<Type> {
var rValue = self.rawValue
return AnyGenerator {
defer { rValue += 1 }
return Type(rawValue: rValue)
}
}
/* use the fact that Type conforms to SequenceType to neatly
initialize your static all array */
static let all = Type().map { $0 }
}
print(Type.all)
// [Type.A, Type.B, Type.C, Type.D, Type.E, Type.F, Type.G, Type.H]
Applying this conformance only to initialize the static all array is possibly overkill, but a plausible alternative in case you'd like to be able to able to use other aspects of your enum conforming to SequenceType
for typeCase in Type() {
// treat each type ...
print(typeCase, terminator: " ")
} // A B C D E F G H
for caseFromEAndForward in Type.E {
print(caseFromEAndForward, terminator: " ")
} // E F G H
flatMap to initialize cases based on a range of rawValue'sFinally, as a variation of @appzYourLife neat solution, in case you have very many cases, you can use a flatMap operation on the range of rawValue's to initialize the static allValues array, e.g.
enum Type: Int {
case A = 0, B, C, D, E, F, G, H
static let all = (A.rawValue...H.rawValue)
.flatMap{ Type(rawValue: $0) }
}
print(Type.all)
// [Type.A, Type.B, Type.C, Type.D, Type.E, Type.F, Type.G, Type.H]
There's, however, not really any practical use for this method as the general size methods (@vacawama:s or the SequenceType above) would always be preferable for enums of many cases. The possibly use case I can see for this is if the rawValue's of the different cases are sequential but not simply by ++, e.g. if the rawValue's are used for some bitmasking
// ...
case A = 0, B = 2, C = 4, D = 8, E = 16, F = 32, G = 64, H = 128
The method above would use a method of brute-forcing through the range of rawValue's, where a minority will actually correspond to actual cases. Somewhat wasteful, but since it's a one-time static initialization, that shouldn't really be an issue.
Why don't you simply add a static property to your enum Type?
enum Type: Int {
case A = 0, B, C
static let all = [A, B, C]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With