Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

parameters with optional closures in swift

I'm using optional closures, but can't find a way to pass on a parameter. Searched everywhere, tried all suggestions, but can't get it to work.

My code:

func DoAlert(title: String
    , message: String
    , actions: String
    , sender: AnyObject?
    , Ctlr : UIViewController
    , SegueString: String?
    , YesClosure: ()->() = {}
    , NoClosure: ()->() = {}
    , StartClosure: ()->() = {}
    , EndClosure: ()->() = {}
    ) {

if (actions.rangeOfString("Ok") != nil {
        alert.addAction(UIAlertAction(title: "OK", style: .Default ) { action -> Void in
            EndClosure()
            })}
} // end function

I want to add a closure for Ok, where the 'self' parameter is needed.

Something like below:

    // add to func doAlert: 
    , OkClosure: (AnyObject)->() = {}


            // add to action Ok (before the EndClosure: 
            OkClosure(sender!)

Getting error on first line: AnyObject is not subtype of ()

If I leave AnyObject out of first line, Getting error: Cannot convert the expression's type 'AnyObject' to type '() => ()'

All other trials give me similar 'Tuple' errors. How do I code the passing of parameters in the optional closures in my code?

like image 529
ReneMusters Avatar asked Apr 09 '15 20:04

ReneMusters


1 Answers

Firstly, to use closures as an argument for a function, you should declare them like so:

func myFunc(closure: (Int) -> Void) {
    // Now I can call closure like so:
    let myInt = 10
    closure(myInt)
}

(As pointed out by @Airspeed Velocity, the parenthesis around Int are not strictly required because there is only one argument. Whether you include them is just personal preference)

Secondly, you can modify the previous function to include an optional closure, as follows: (Note the ? and parenthesis around the closure that indicate the closure is an optional, not the return type)

func myFunc(closure: ((Int) -> Void)?) {
    // Now when calling the closure you need to make sure it's not nil.
    // For example:
    closure?(10)
}

Thirdly, to add a default value of nil, which is what it looks like you're trying to do with the = {} on the end of YesClosure: ()->() = {}, you could do:

func myFunc(closure: ((Int) -> Void)? = nil) {
    // Still need to make sure it's not nil.
    if let c = closure {
        c(10)
    }
}

Finally, just as a note, you can set the names of the arguments of the closure, which can make it easier to identify what you're passing to the closure when calling it. For example:

(Note - here parenthesis are required around value: Int)

func myFunc(closure: ((value: Int) -> Void)) {
    closure(value: 10)
}

Even more finally, you could use typealias. According to the documentation:

A type alias declaration introduces a named alias of an existing type into your program.

Here's an example of how to use it with a closure:

typealias MyClosureType = () -> Void

func myFunc(closure: MyClosureType) {
    closure()
}

Hope that helps!

like image 149
ABakerSmith Avatar answered Sep 21 '22 14:09

ABakerSmith