4

It seems that closures of compatible parameter and return types can't be cast( up or down ). I want to store arrays of callbacks in a Dictionary, where the key can be used to determine the type of the callback's parameter. Just casting won't do:

typealias AnyCallback = ( value: AnyObject )-> Void
typealias SpecializedCallback = ( value: UIView ) -> Void

let callback : SpecializedCallback =
{
    ( value: UIView ) in
    println( value )
}

if let castCallback : AnyCallback = callback as? AnyCallback
{
    // block never executed
    println( "did cast callback" )
    castCallback( value: self.view )
}

As a workaround, it is possible to wrap the callback in a generic class which will handle parameter type casting:

final class GenericCallback< T >
{
    func executeCallback( value: Any? ) -> Void
    {
        if let specificValue = value as? T
        {
            specificCallback( value: specificValue )
        }
    }

    init( callback: ( value: T? )->Void )
    {
        self.specificCallback = callback
    }

    private let specificCallback : ( value: T? )->Void
}

As executeCallback captures self, it can be added directly to an array of callbacks safely, removing the need to keep a reference to the wrapper:

typealias GenericCallbackType = ( value: Any? ) -> Void

var callbackArray : [ GenericCallbackType ] = []

let specializedCallback =
{
    ( value: UIView? ) -> Void in
    println( value )
}

let wrappedCallback = GenericCallback( callback: specializedCallback )

callbackArray.append( wrappedCallback.executeCallback )

It works fine, but of course I'm in the market for a simpler solution should there be one...

Gregzo
  • 1,194
  • 7
  • 18

1 Answers1

4

What you're trying to do can't be done in Swift (right now).

It's like you're trying to cast an object Dog to an object Cat, that have the following implementation:

class Cat {
    var value: UIView!
}

class Dog {
    var value: AnyObject!
}

I hope this comes in a future version of Swift.

vrwim
  • 13,020
  • 13
  • 63
  • 118