在學習Swift 3的過程當中整理了一些筆記,若是想看其餘相關文章可前往《Swift 3必看》系列目錄git
在以前,一個函數的參數的閉包的捕捉策略默認是escaping,若是是一個非逃逸閉包須要顯示的添加聲明@noescape。感興趣的能夠看我之前寫過一篇介紹:Swift中被忽略的@noescape。簡單的介紹就是若是這個閉包是在這個函數結束前內被調用,就是非逃逸的即noescape。若是這個閉包是在函數執行完後才被調用,調用的地方超過了這函數的範圍,因此叫逃逸閉包。github
舉個例子就是咱們經常使用的masonry或者snapkit的添加約束的方法就是非逃逸的。由於這閉包立刻就執行了。json
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)
}複製代碼
網絡請求請求結束後的回調的閉包則是逃逸的,由於發起請求後過了一段時間後這個閉包才執行。好比這個Alamofire裏的處理返回json的completionHandler閉包,就是逃逸的。swift
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
)
}複製代碼
就像我以前寫的那篇標題,不少人在寫閉包參數的時候老是忽略去判斷這個閉包是不是逃逸的。這對閉包的內存管理優化不太友好,都被當作了逃逸閉包處理。因此在3中作出了一個對調的改變:全部的閉包都默認爲非逃逸閉包,再也不須要@noescape;若是是逃逸閉包,就用@escaping表示。好比下面的一段代碼,callBack在函數執行完後1秒才執行,因此是逃逸閉包。api
func startRequest(callBack: ()->Void ) {
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 1) {
callBack()
}
}複製代碼
這樣就須要顯示的聲明@escaping才能編譯經過。網絡