I made some notes while learning Swift 3. If you want to read other related articles, you can go to the Swift 3 Must-see series

Previously, the capture policy for closure of a function argument was escaping by default, requiring the addition declaration @noescape to be displayed if it was a non-escape closure. For those of you interested, I wrote an introduction before: the neglected @noescape in Swift. The simple introduction is that if the closure is called within the end of the function, it is non-escape, i.e. noescape. If the closure is called after the function has finished executing, it is called outside the scope of the function, so it is called an escape closure.

For example, the navigation or Snapkit method for adding constraints is non-escaping. Because the closure is going to execute immediately.

  public func snp_makeConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) - >Void {
        ConstraintMaker.makeConstraints(view: self, file: file, line: line, closure: closure)
    }Copy the code

The closure of a callback after a network request is escaped, because some time has passed since the request was initiated before the closure is executed. For example, the completionHandler closure in Alamofire, which returns JSON, is escaped.

    public func responseJSON(
        queue queue: dispatch_queue_t? = nil,
        options: NSJSONReadingOptions = .AllowFragments,
        completionHandler: Response<AnyObject, NSError> -> Void)
        -> Self
    {
        return response(
            queue: queue,
            responseSerializer: Request.JSONResponseSerializer(options: options),
            completionHandler: completionHandler
        )
    }Copy the code

As I wrote earlier in the title, many people write closure arguments without trying to determine if the closure is escaped. This is not very friendly to closure memory management optimizations and is treated as an escape closure. So a reversal was made in 3: all closures default to non-escape closures, eliminating the need for @noescape; If it is an escape closure, @escaping. For example, in the following code, the callBack is executed one second after the function is executed, so it is an escape closure.

func startRequest(callBack: (a)->Void ) {
    DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 1) { 
        callBack()
    }
}Copy the code

This requires the statement @escaping to be displayed to compile.

Related links: SE-0103: Make non-escaping closures the default