Search code examples
swiftescapingclosuresvoidswift5

In Swift, What is the difference between (()->()) and @escaping () -> Void?


What is the difference between (()->()) and @escaping () -> Void?

func foo(_ completion: (() -> ()) { }

func boo(_ completion: @escaping () -> Void) { }

Solution

  • Quick Excerpt


    Escaping Closures
    A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

    One way that a closure can escape is by being stored in a variable that is defined outside the function. As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn’t called until the operation is completed—the closure needs to escape, to be called later. For example:

    var completionHandlers: [() -> Void] = []
    func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
        completionHandlers.append(completionHandler)
    }
    

    The someFunctionWithEscapingClosure(_:) function takes a closure as its argument and adds it to an array that’s declared outside the function. If you didn’t mark the parameter of this function with @escaping, you would get a compile-time error.”

    “let alsoIncrementByTen = incrementByTen
    alsoIncrementByTen()
    // returns a value of 50
    
    incrementByTen()
    // returns a value of 60
    

    The example above shows that calling alsoIncrementByTen is the same as calling incrementByTen. Because both of them refer to the same closure, they both increment and return the same running total.

    Escaping Closures A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

    One way that a closure can escape is by being stored in a variable that is defined outside the function. As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn’t called until the operation is completed—the closure needs to escape, to be called later. For example:

    var completionHandlers: [() -> Void] = []
    func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
        completionHandlers.append(completionHandler)
    }
    

    The someFunctionWithEscapingClosure(_:) function takes a closure as its argument and adds it to an array that’s declared[…]”


    Excerpt From: Apple Inc. “The Swift Programming Language (Swift 5.2).” Apple Books. https://books.apple.com/us/book/the-swift-programming-language-swift-5-2/id881256329


    In other words, @escaping closures require the use of self, if you are trying to reference methods within the current object. i.e. Completion Closures of SKActions are a really good example of this.

    And non escaping closure's don't require the use of self. Because they weren't used to reference an object.