Passing closures into functions

suggest change

Functions may accept closures (or other functions) as parameters:

func foo(value: Double, block: () -> Void) { ... }
func foo(value: Double, block: Int -> Int) { ... }
func foo(value: Double, block: (Int, Int) -> String) { ... }

Trailing closure syntax

If a function’s last parameter is a closure, the closure braces \{/\} may be written after the function invocation:

foo(3.5, block: { print("Hello") })

foo(3.5) { print("Hello") }

dispatch_async(dispatch_get_main_queue(), {
    print("Hello from the main queue")
})

dispatch_async(dispatch_get_main_queue()) {
    print("Hello from the main queue")
}

If a function’s only argument is a closure, you may also omit the pair of parentheses () when calling it with the trailing closure syntax:

func bar(block: () -> Void) { ... }
bar() { print("Hello") }

bar { print("Hello") }

@noescape parameters

Closure parameters marked @noescape are guaranteed to execute before the function call returns, so using self. is not required inside the closure body:

@noescape
class MyClass {
    var x = 0
    func showExamples() {
        // error: reference to property 'x' in closure requires explicit 'self.' to make capture semantics explicit
        executeLater { x = 1 }

        executeLater { self.x = 2 }  // ok, the closure explicitly captures self

        // Here "self." is not required, because executeNow() takes a @noescape block.
        executeNow { x = 3 }

        // Again, self. is not required, because map() uses @noescape.
        [1, 2, 3].map { $0 + x }
    }
}

Swift 3 note:

Note that in Swift 3, you no longer mark blocks as @noescape. Blocks are now not escaping by default. In Swift 3, instead of marking a closure as non-escaping, you mark a function parameter that is an escaping closure as escaping using the “@escaping” keyword.


throws and rethrows

Closures, like other functions, may throw errors:

throws

The function may, of course, pass the error along to its caller:

throwsthrows

However, if the block passed in doesn’t throw, the caller is still stuck with a throwing function:

// It's annoying that this requires "try", because "print()" can't throw!
try executeNowOrThrow { print("Just printing, no errors here!") }

The solution is rethrows, which designates that the function can only throw if its closure parameter throws:

throwsrethrowscan

Many standard library functions use rethrows, including map(), filter(), and indexOf().

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents