How to detect that parameter is a tuple of two arbitrary types?

前端 未结 2 761
鱼传尺愫
鱼传尺愫 2021-01-01 04:56

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

相关标签:
2条回答
  • 2021-01-01 05:02

    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
    
    0 讨论(0)
  • 2021-01-01 05:17

    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
    
    0 讨论(0)
提交回复
热议问题