Reputation: 11008
Can one use an array of types to refactor the following condition?
vc is ViewController1 || vc is ViewController2 || vc is ViewController3...
Upvotes: 1
Views: 121
Reputation: 130200
One possible way:
let types: [Any.Type] = [CGFloat.self, Double.self, Float.self]
let myVar = 10.0
let isFloat = types.contains { myVar.dynamicType == $0 }
print("Is float: \(isFloat)")
Unfortunately, Swift doesn't allow us to test myVar is $0
directly with dynamic types. Therefore this is not very useful if we want to check subclasses.
I would really recommend the solution with a custom protocol.
Upvotes: 1
Reputation: 4731
You could make an extension like this:
import Foundation
extension SequenceType where Generator.Element == Any.Type{
func containsType(object:Any)->Bool{
let mirror = Mirror(reflecting: object)
let objectType = mirror.subjectType
return self.contains{objectType == $0}
}
}
And you call it like this:
if [ViewController1.self, ViewController2.self, ViewController3.self].containsType(vc){
//statement is true
}else{
//Statement is false
}
In the documentation here it says This type may differ from the subject's dynamic type when self is the superclassMirror() of another mirror.
This is in regards to .subjectType
.
Upvotes: 2
Reputation: 22290
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.
Upvotes: 2