Andrei Andrei - 6 months ago 13
Swift Question

Check if a view controller one of few possible types in Swift

Can one use an array of types to refactor the following condition?

vc is ViewController1 || vc is ViewController2 || vc is ViewController3...

Answer

YES, but you shouldn't.

You CAN create an array of types:

let types:[Any.Type] = [CGFloat.self, Double.self, Float.self]

You MUST specify the type of the array as [Any.Type]. It can't figure it out on it's own.

You can even get a type from a variable that matches those.

let double = 42.13
double.dynamicType --> Double.Type
types.contains(double.dynamicType) --> true

As @werediver suggests, probably the most swift idiomatic way to do such in swift is to define an empty protocol:

protocol ExaltedViewController { }

and then conform your various classes to it:

extension ViewController1:ExaltedViewController { }
extension ViewController2:ExaltedViewController { }
extension ViewController3:ExaltedViewController { }

Then you can just test with

if vc is ExaltedViewController { ... }

The advantage of doing this is that you don't have to have a centrally managed list. If your code were a framework, where you wanted other peoples view controllers to be added into that list, they could simply adopt the protocol, rather than having to hunt down where the special list was and edit it.

An alternate approach is to use a switch statement with stacked is tests. Consider the following:

func typeWitch(something:Any) { // type divining function
    switch something {
    case is CGFloat, is Float, is Double:
        print("it's got floating point superpowers")
    case is Int, is Int16, is Int32, is Int8, is Int64:
        print("it's a signed int")
    default:
        print("it's something else")
    }
}

typeWitch("boo")
typeWitch(13)
typeWitch(42.42)

And of course, you can put the two approaches together.