Swift3.0 闭包回调传递参数 – @escaping
非逃逸闭包:
如果一个闭包被作为一个参数传递给一个函数, 函数在return之前被立即执行,那么这个闭包是非逃逸闭包
常用的masonry或者snapkit的添加约束的方法就是非逃逸的。因为这闭包马上就执行了。
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) }
逃逸闭包:
如果一个闭包被作为一个参数传递给一个函数,并且在函数return之后才被唤起执行,那么这个闭包是逃逸闭包.并且这个闭包的参数是可以“逃出”这个函数体外的.
Swift3 中做出了一个与Swift2 对调的改变:所有的闭包都默认为非逃逸闭包,不再需要@noescape;如果是逃逸闭包,就用@escaping表示
网络请求请求结束后的回调的闭包则是逃逸的,因为发起请求后过了一段时间后这个闭包才执行
比如这个Alamofire里的处理返回json的completionHandler闭包,就是逃逸的。
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 ) }
比如下面的一段代码,callBack在函数执行完后10秒才执行,所以是逃逸闭包。
func startRequest(callBack: ()->Void ) { DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 10) { callBack() } }
=================================================
创建默认不可逃逸闭包的好处:最明显的好处就是编译器优化你的代码的性能和能力.如果编译器知道这个闭包是不可逃逸的,它可以关注内存管理的关键细节.
而且可以在不可逃逸闭包里放心的使用self关键字,因为这个闭包总是在函数return之前执行,你不需要去使用一个弱引用去引用self.
//加载请求数据 func loadData(completion: @escaping (_ result:[String]) -> ()) -> () { DispatchQueue.global().async { print("耗时操作 \(Thread.current)") //获取到的json结果数据 let json = ["姓名","年龄","爱好"] //主队列回调 DispatchQueue.main.async { print("主线程更新 UI \(Thread.current)") //回调异步获取的结果 completion(json) } } } //调用: //尾随闭包, //如果函数的最后一个参数是闭包,函数参数可以提前结束,最后一个参数直接使用{},包装闭包的代码 loadData { (result) in print("获取结果 \(result)") } //按照函数本身的格式编写 loadData(completion: { (result) -> () in print("获取结果 \(result)") })