Can Swift Closures Be Set to a Default Value When Used as a Parameter in a Function

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

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.

Can swift functions have a default completion handler?

You can either do this:

func foo(completion: (success: Bool) -> Void = {_ in }) {
completion(success:true)
}

Or this:

func foo(completion: ((success: Bool) -> Void)? = nil) {
completion?(success:true)
}

How to optionally pass in values to a closure in Swift?

For a regular method, you can provide a default value for a parameter:

func myCallback(#error: NSError!, samples: [HKQuantitySample]? = nil, average: Double? = nil) {
}

myCallback(error: nil)

These parameters with default values should be at the end of the argument list.

This doesn't work in your case, since you're not defining a method; you're just specifying the method signature that callers need to pass in for the callback. You can say "pass in a method that takes an Int", for example, but there's no way currently to say "pass in a method that takes an Int and uses a default of 0 if I don't pass anything in".

Remember, optional values just mean the existence of a value is optional and the thing can be nil.

Difficulties to assign default value to a parameter of a function

I don't think that is possible. The default value is inserted at the calling site, and therefore needs to be public, see also
Access control in swift 4.

A possible workaround would be to make the parameter optional,
and substitute nil by the default value locally:

class Foo {
private static let DefaultValue = 10

public func doTask(amount: Int? = nil) {
let amount = amount ?? Foo.DefaultValue
// ...
}
}


Related Topics



Leave a reply



Submit