Updating closures to Swift 3 - @escaping

前端 未结 2 1233
臣服心动
臣服心动 2020-11-30 23:35

I\'ve updated my code to Xcode 8.0 beta 6 but I got stuck with what seems to be about the new non escaping closure default. In the following code Xcode suggests to add

相关标签:
2条回答
  • 2020-12-01 00:00

    @noescape

    From xcode 8 beta 6 @noescape is the default. Prior to that, @escaping was the default. Anybody updating to swift 3.0 from previous versions might face this error.

    You can not store a @noescape closure inside a variable. Because if you can store a closure inside a variable, you can execute the closure from anywhere in your code. But @noescape states that the closure parameter can not escape the body of the function.

    This will give compiler error in Xcode 8

    class MyClass {
    
        var myClosure: (() -> ())?
    
        func doSomething(finishBlock: () -> ()) {
            myClosure = finishBlock    // ‼️ Error: Assigning non-escaping parameter 'finishBlock' to an @escaping closure
        }
    }
    

    This will compile ok (explicitly write @escaping)

    class MyClass {
    
        var myClosure: (() -> ())?
    
        func doSomething(finishBlock: @escaping () -> ()) {
            myClosure = finishBlock
        }
    }
    

    Benefits of @noescape:

    • Compiler can optimize your code for better Performance
    • Compiler can take care of memory management
    • There is no need to use a weak reference to self in the closure


    For details check out: Make non-escaping closures the default

    0 讨论(0)
  • 2020-12-01 00:14

    Swift 3: closure parameter attributes are now applied to the parameter type, and not the parameter itself

    Prior to Swift 3, the closure attributes @autoclosure and @noescape used to be attributes to the closure parameter, but are now attributes to the parameter type; see the following accepted Swift evolution proposal:

    • SE-0049: Move @noescape and @autoclosure to be type attributes

    Your specific question pertain to parameter type attribute @escaping (for which the same new rule applies), as described in the accepted Swift evolution proposal to let closure parameters be non-escaping by default:

    • SE-0103: Make non-escaping closures the default

    These proposals are now both implemented in the beta stage of Xcode 8 (see release notes for Xcode 8 beta 6; dev. account login needed for access)

    New in Xcode 8 beta 6 - Swift Compiler: Swift Language

    Closure parameters are non-escaping by default, rather than explicitly being annotated with @noescape. Use @escaping to indicate that a closure parameter may escape. @autoclosure(escaping) is now written as @autoclosure @escaping. The annotations @noescape and @autoclosure(escaping) are deprecated. (SE-0103)

    ...

    New in Xcode 8 beta – Swift and Apple LLVM Compilers: Swift Language

    The @noescape and @autoclosure attributes must now be written before the parameter type instead of before the parameter name. [SE-0049]

    Hence, you use the non-default @escaping attribute as follows; applied to the type of the closure parameter, rather than the parameter itself

    func doSomething(withParameter parameter: Int, completion: @escaping () -> ()) {
        // ...
    }
    

    (Including my answer to a question in an upvoted comment below, as comments are not persistent data on SO)

    @Cristi Băluță: "What does escaping do? Never seen this keywords before swift3 auto-conversion ... "

    See e.g. the link to the SE-0103 evolution proposal above (as well as the quoted text from the beta 6 release notes): previously, closure parameters were escaping by default (hence no need for the existence of an explicit annotation for escaping), but are now instead non-escaping, by default. Hence the addition of @escaping to explicitly annotate that a closure parameter may escape (contrary to its default behaviour). This also explains why @noescape is now deprecated (no need to annotate the default behaviour).

    For explaining what it means that a closure parameter is escaping, I quote the Language Reference - attributes:

    "Apply this attribute to a parameter’s type in a method or function declaration to indicate that the parameter’s value can be stored for later execution. This means that the value is allowed to outlive the lifetime of the call."

    0 讨论(0)
提交回复
热议问题