Sunday, June 15, 2014

Holding closures in a member variable

The next problem that was not obvious was that I wanted to have a callback to my main routine from the picker data source.   After some experimentation I declared the following:

    var callback:(value:AnyObject[]);

And I called the initializer with:

init(selectedCall:(value:AnyObject[]), arrays: Array<AnyObject> ... )


However when I declared the following:
 let returnValue = { (selectedRows: AnyObject[]) in
            println("selected row \(selectedRows)");
        };
        
        // Pass the callback to the new delegate, as well as the list of arrays.
        var delegate=PickerProvider(selectedCall:returnValue

            ,arrays:numDice,dieTypes,modRolls,modifiers);

This resulted in the compile time error of:
'(value: @lvalue AnyObject[]) -> $T3' is not identical to '(value: AnyObject[])'
'(AnyObject[]) -> ()' is not convertible to 'AnyObject[]'

What really happened is explained in Apple's swift manual in a note under functions:

Strictly speaking, the sayGoodbye function does still return a value, even though no return value is defined. Functions without a defined return type return a special value of type Void. This is simply an empty tuple, in effect a tuple with zero elements, which can be written as ().

The Apple manual has a lot of explanations for how to use closures for existing libraries, but not a lot for how to write your own functions to use closures.  The problem is that my return Value is actually

(selectedRows: AnyObject[])->() 

While the compiler will currently let you declare variables and member functions without the ->(), it will not consider those the same as the real function.

The solution to this one is to declare my code as:

    var callback:(value:AnyObject[])->();
With an initializer of:
    init(selectedCall:(value:AnyObject[])->(), arrays: Array<AnyObject> ... )



No comments:

Post a Comment