Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can swift closures be set to a default value when used as a parameter in a function?

Tags:

macos

ios

swift

A pretty handy feature of Swift functions is that function parameters can have default values:

func someFunction(parameterWithDefault: Int = 42) {     //if no arguments are passed to the function call,     //value of parameterWithDefault is 42 } 

If a parameter is a closure, is there a way to make it have a default value? See the example below:

func sendBody(     body: NSData? = nil,     success: (data: NSData) -> Void,     failure: (data: NSData?) -> Void) { } 

Is there a way to not force the developer to pass a value for success or failure when calling sendBody?

like image 852
Eric Avatar asked Jul 01 '15 10:07

Eric


People also ask

Is it possible to give a default value to a function parameter Swift?

You can define a default value for any parameter in a function by assigning a value to the parameter after that parameter's type. If a default value is defined, you can omit that parameter when calling the function.

How do you set a parameter to default value?

The default parameter is a way to set default values for function parameters a value is no passed in (ie. it is undefined ). In a function, Ii a parameter is not provided, then its value becomes undefined . In this case, the default value that we specify is applied by the compiler.

How do closures capture references to variables by default?

In Swift, closures capture the variables they reference: variables declared outside of the closure but that you use inside the closure are retained by the closure by default, to ensure they are still alive when the closure is executed.


2 Answers

Yes, functions are just values, so you can supply them as defaults

// just to show you can do it with inline closures or regular functions func doNothing<T>(t: T) -> Void { }  func sendBody(     body: NSData? = nil,     success: (data: NSData) -> Void = { _ in return },     failure: (data: NSData?) -> Void = doNothing ) {  } 

Alternatively, you could make them optional, that way you can detect if the caller passed one:

func sendBody(     body: NSData? = nil,     success: ((NSData) -> Void)? = nil,     failure: ((NSData?) -> Void)? = nil     ) { success?(NSData()) }  sendBody(success: { _ in print("ah, yeah!") }) 

Also worth noting if you’re doing this: if the caller uses the trailing closure syntax, this will be the last closure in the argument list. So you want the last one to be the one the user is most likely to want to supply, which is probably the success closure:

func sendBody(     body: NSData? = nil,     success: ((NSData) -> Void)? = nil,     failure: ((NSData?) -> Void)? = nil     ) {     if success != nil { print("passed a success closure") }     if failure != nil { print("passed a failure closure") } }  // this prints "passed a failure closure" sendBody { data in     print("which closure is this?") } 

Other than this, the order in the function declaration doesn’t matter to the caller – defaulted arguments can be supplied in any order.

like image 154
Airspeed Velocity Avatar answered Sep 27 '22 16:09

Airspeed Velocity


You could do something like this,

let defaultSuccess: NSData -> Void = {     (data: NSData) in  }  let defaultFailure: NSData? -> Void = {     (data: NSData?) in }  func sendBody( body: NSData? = nil, success: (data: NSData) -> Void = defaultSuccess, failure: (data: NSData?) -> Void = defaultFailure) { } 

Then, you may be able to call either one of these methods. Notice sendBody which is called with default parameters.

sendBody() sendBody(body: , success: , failure: ) 

You can also call with all the variants like passing just one of the argument in the above method, for that you have to call it with named parameter.

sendBody() sendBody(body:)  sendBody(failure: ) sendBody(success:)  sendBody(body: , success: , failure: ) 
like image 31
Sandeep Avatar answered Sep 27 '22 18:09

Sandeep