What I am actually doing is more complex but it comes down to being able to implement function to detect that something is a tuple, regardless of what the are the types of i
In Swift 3, it's now done this way:
func isTuple(value: Any) -> Bool {
if let type = Mirror(reflecting: value).displayStyle, type == .tuple {
return true
}
return false
}
isTuple(value: ()) // true
isTuple(value: (1, 2) // true
isTuple(value: 3) // false
You can use Swift's baby introspection methods to get at this:
func isTuple(b: Any) -> Bool {
return reflect(b).disposition == MirrorDisposition.Tuple
}
Note that reflect
is largely undocumented and may only be there as support for the playground / debugger, but as far as I know this is the only way to do this.
To achieve this you need to drill down into what reflect()
gives you, which is a struct that conforms to MirrorType
, which I call a reflection, for lack of a better term. You can subscript the reflection of a tuple to get reflections of the tuples members, and then get the value back out as Any
. At that point you can use optional binding to safely rediscover the underlying type:
func process(value: Any) {
println("Any \(value)")
}
func process(value: String) {
println("String \(value)")
}
func processTuple(b: Any) -> Bool {
let isTuple = reflect(b).disposition == MirrorDisposition.Tuple
let r = reflect(b)
for i in 0..<r.count {
println(r[i].0) // string holding tuple part name: ".0", ".1", etc
println(r[i].1.value) // the value of that tuple part: "aa", 1.2
process(r[i].1.value) // calls process(Any)
if let val = r[i].1.value as? String {
process(val) // calls process(String)
}
}
return isTuple
}
let myString = "aa"
let myDouble = 1.2
processTuple((myString, myDouble)) //returns false
Output:
.0
aa
Any aa
String aa
.1
1.2
Any 1.2