Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check for Enum types in Swift?

Tags:

enums

swift

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
}
like image 572
mbonness Avatar asked Jan 11 '16 17:01

mbonness


2 Answers

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.

like image 160
dfrib Avatar answered Nov 07 '22 20:11

dfrib


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)
}
like image 39
user3441734 Avatar answered Nov 07 '22 19:11

user3441734