Pass Optional Block or Closure to a Function in Swift

Pass optional block or closure to a function in Swift

Although not as hard to remember as the Objective-C block syntax, it's far from obvious. The notConnected parameter is optional in this example:

    func whenConnected(block: Void -> Void, notConnected: ((Void) -> Void)?, showErrorMessage: Bool) -> Void {

let connected = Reachability.isConnectedToNetwork()

if connected {
block()
} else {
notConnected?()
}

if showErrorMessage {
// your error handling //
}
}

How does one make an optional closure in swift?

You should enclose the optional closure in parentheses. This will properly scope the ? operator.

func then(onFulfilled: ()->(), onReject: (()->())?){       
if let callableRjector = onReject {
// do stuff!
}
}

Swift optional escaping closure parameter

There is a SR-2552 reporting that @escaping is not recognizing function type alias. that's why the error @escaping attribute only applies to function types. you can workaround by expanding the function type in the function signature:

typealias Action = () -> ()

var action: Action? = { }

func doStuff(stuff: String, completion: (@escaping ()->())?) {
print(stuff)
action = completion
completion?()
}

func doStuffAgain() {
print("again")
action?()
}

doStuff(stuff: "do stuff") {
print("swift 3!")
}

doStuffAgain()

EDIT 1::

I was actually under a xcode 8 beta version where the bug SR-2552 was not resolved yet. fixing that bug, introduced a new one(the one you're facing) that is still open. see SR-2444.

The workaround @Michael Ilseman pointed as a temporary solution is remove the @escaping attribute from optional function type, that keep the function as escaping.

func doStuff(stuff: String, completion: Action?) {...}

EDIT 2::

The SR-2444 has been closed stating explicitly that closures in parameters positions are not escaping and need them to be marked with @escaping to make them escaping, but the optional parameters are implicitly escaping, since ((Int)->())? is a synonyms of Optional<(Int)->()>, optional closures are escaping.

Function with optional completion block in Swift

In Swift 3:

func foo(completionBlock: (String) -> () = { _ in }) {}

Passing optional callback into Swift function

Update for Swift 3/4:

An optional is no longer a boolean expression, and the
deprecated func dismissModalViewControllerAnimated(animated: Bool)
is no longer available in Swift.

Simply declare the completion parameter as an optional closure, and
pass it on to

func dismiss(animated flag: Bool, completion: (() -> Void)? = nil)

which takes an optional closure as well:

func dismiss(completion: (() -> Void)? = nil) {
self.dismiss(animated: true, completion: completion)
}

Old (Swift 1.x?) answer:

Declare the completion parameter as (implicitly unwrapped) optional closure (() -> Void)!:

func dismiss(completion: (() -> Void)!) {
if (completion) {
return self.dismissViewControllerAnimated(true, completion: completion)
}
self.dismissModalViewControllerAnimated(true)
}

But note that you can call

self.dismissViewControllerAnimated(true, completion: completion)

in any case, because the completion parameter of that function is optional as well.
And

func dismissModalViewControllerAnimated(animated: Bool)

is actually marked as deprecated.

parameters with optional closures in swift

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!



Related Topics



Leave a reply



Submit