How to check for Enum types in Swift?
Solution 1
enum Things {
case Thing1
case Thing2
}
let something:Any = Things.Thing1
something.dynamicType == Things.self // true
update based on discussion ..
protocol P {}
enum Things:P {
case Thing1
case Thing2
}
enum Things2:P{
case Things21
}
let something:Any = Things.Thing1
something.dynamicType == Things.self // true
if let p = something as? P {
print(true)
}
let somethingelse: Any = Things2.Things21
if let p = somethingelse as? P {
print(true)
}
Solution 2
Since Mirror.displayStyle
is an optional enumeration, preferably use conditional unwrapping and type checking in same statement.
You could extend Mirror.displayStyle
by an .equals
method to make it readily accessible in case you want to do this enum check frequently.
extension Mirror.DisplayStyle {
func equals(displayCase: Mirror.DisplayStyle) -> Bool {
return self == displayCase
}
}
enum Things {
case Thing1
case Thing2
}
let something:Any = Things.Thing1
let mirror = Mirror(reflecting: something)
/* short form: using nil coalescing and ternary conditional operator */
mirror.displayStyle?.equals(.Enum) ?? false ? print("Reflected type is an Enum") : ()
/* another option: or using if-let */
if let _ = mirror.displayStyle?.equals(.Enum) {
print("Reflected type is an Enum")
}
Note that you needn't explicitly create and store a Mirror
instance for this check, but can do it all in one expression, for some instance something
of type Any
:
Mirror(reflecting: something).displayStyle?.equals(.Enum) ?? false ? print("Reflected type is an Enum") : ()
Finally, if you're just interesting in doing some simple action base on the DisplayStyle
case of different Any
instances, you could create a function that switches over the different cases of this enum. Below, the "simple action" just prints the case.
//...
func foo(mirror: Mirror) {
if let dispStyle = mirror.displayStyle {
switch(dispStyle) {
case .Class: print("Reflected type is a Class")
case .Collection: print("Reflected type is a Collection")
case .Dictionary: print("Reflected type is a Dictionary")
case .Enum: print("Reflected type is an Enum")
case .Optional: print("Reflected type is an Optional")
case .Set: print("Reflected type is a Set")
case .Struct: print("Reflected type is a Struct")
case .Tuple: print("Reflected type is a Tuple")
}
}
}
let something: Any = Things.Thing1
foo(Mirror(reflecting: something))
See also Language Reference for Mirror.DisplayStyle.
![mbonness](https://i.stack.imgur.com/wXbWV.png?s=256&g=1)
mbonness
Updated on July 26, 2022Comments
-
mbonness almost 2 years
I am writing a serializer that can serialize enums and other Swift types (strings, objects, etc.). So I need to check if an Any parameter passed into my serializer is an Enum or something else. It seems like the only way to do this in Swift is using reflection. Does the code below seem reasonable or is there a better way to check for Enum types?
enum Things { case Thing1 case Thing2 } let something:Any = Things.Thing1 let mirror = Mirror(reflecting: something) if (mirror.displayStyle == .Enum) { print("Reflected type is Enum") // works }
-
Cristik over 8 yearsWhy would you need to check the type?
-
dfrib over 8 yearsIf you want to know the "underlying type", the I believe
mirror.displayStyle
is a good option. @Cristik: One situation where one might want to know the "underlying type" is when e.g. an array ofAny
contains optional as well as non-optional entries; checking.displayStile == .Optional
could be one approach to prepare for (possibly) casting theAny
elements to native Swift types. -
user3441734 over 8 yearsEnum is not a type in Swift (as struct is not a type, Optional is not a type ... ), Mirror.DisplayStyle is enum with case Enum defined.
-
Cristik over 8 years@dfri string comparison is not a good approach, I was merely curious about the context of the problem as the might be some better approaches that detecting type at runtime.
-
Cristik over 8 years@user3441734: if it's not a type, then what an Enum is?
-
user3441734 over 8 years@Cristik Mirror.DisplayStyle is type with case Enum defined. enum is keyword, like struct is. with help of enum keyword you can define your own type Things, as OP did.
-
dfrib over 8 years@Cristik I see no string comparison above. As user3441734 says,
Mirror.DisplayStyle
is an enum itself, so the comparison in question is checking if.DisplayStyle
holds case.Enum
. -
user3441734 over 8 years@Cristik func is not type too. func foo()->Void represents a type. that is why let f = foo works as expected.
-
Cristik over 8 years@dfri mea culpa that, I assumed it's a string. In this case your code sample is a valid one. Still trying to understand the domain of the OP's problem, though :)
-
Cristik over 8 years@user3441734 I understand the difference between keywords and actual types ;) But why do you insist that
Optional
is not a type? -
user3441734 over 8 years@Cristic Optional<T> is generic construct, like Array<T>. Array<Int> represents a type, Array<Double> represents different type, Optional<Int> and Optional<String> are two different types. EDIT!!! SORRY!!! Optional<Wrapped> is a type!! My mistake!!
-
user3441734 over 8 years@Cristik now i am a little bit disoriented if Optional is a type or not :-). What do you think about Optional ?
-
Cristik over 8 years@user3441734
Optional
is a type, and it's a generic type -
user3441734 over 8 years@Cristik ... yes, and Array<Element> is too. For a moment I was 'out of service' :-)
-
dfrib over 8 yearsNote that
Optional
is indeed a type, per se, but is more of a wrapper type w.r.t. it's type specifics:Optional
is, specifically, an enumeration, which can be descriped (somewhat simplified) asenum Optional<T>
with only two cases,.None
and.Some(T)
.
-
-
Cristik over 8 yearsWhat if the argument is another enum?
-
user3441734 over 8 years@Cristik I updated my notes, you are right Optional<Wrapped> is a type!@Cristik in that case it is another Swift type. enum doesn't represent a type, as struct etc. Things is a type in this example, you can instantiate it.
-
mbonness over 8 yearsThis is nice but I was looking for something a little bit more generic, since my program will be using a lot of different enums I do not want to test for each of them individually.
-
user3441734 over 8 years@mbonness the information that "type is an Enum" is useful for something else than debug log etc. ?? Maybe for you can works if your own Things and other user-defined types conforms to some well defined protocol. than you can try to cast all your instances to that common protocol.
-
ScottyBlades almost 4 yearsAre you missing an argument for the equals function?
-
dfrib almost 4 years@ScottyBlades I wrote this over 4 years ago, so I'm not really sure what you are referring to; is seems I intentionally design the
equals
function with a single function parameter, and afaics, all usages of it provide exactly one argument to it. Is the example no longer compiling? (Possible as this was probably based on ~Swift 3). If you are actively working with Swift and can update/approve the answer, please feel free to submit an edit proposal! (I rarely use Swift myself nowadays).