要理解@escaping浦辨,首先需要理解closure蹬竖, 要理解closure,首先理解匿名函數(shù)。
先理解匿名函數(shù)
要在Swift中構(gòu)造匿名函數(shù)币厕,需要:
創(chuàng)建函數(shù)體列另,包括花括號,但是不需要函數(shù)聲明
如果必要旦装,將函數(shù)的參數(shù)列表與返回類型作為花括號中的第一行页衙,后跟關(guān)鍵字in.
例子1: 將以下函數(shù)變成匿名函數(shù):
func whatToAnimate(){
self.myButton.frame.origin.y += 20
}
匿名函數(shù)版本:
{
() -> () in
self.myButton.frame.origin.y += 20
}
例子2: 有參數(shù)的具名函數(shù):
func whatToDoLater(finished: Bool){
print("finished: \(finished)")
}
匿名函數(shù)版本:
{
(finished: Bool) -> () in
print("finished: \(finished)")
}
可省略的地方:
省略返回類型
沒有參數(shù)可以省略 in 這一樣
省略參數(shù)類型
省略圓括號,這個是如果就一個參數(shù)同辣,并且我們編譯器可以推斷出其類型的話
省略 in拷姿, 直接用名字比如 $0
省略參數(shù)名,用_代替
省略函數(shù)實參標(biāo)簽(又叫尾函數(shù)
...
一路省略下來旱函,匿名函數(shù)真是節(jié)約响巢。
再理解閉包
理解匿名函數(shù)之后,我們來看閉包的表達式:
{ (parameters) -> return type in
statements
}
這就是匿名函數(shù)啊棒妨,而我們叫它閉包則是因為:
閉包可以捕獲和存儲其所在上下文中任意常量和變量的引用踪古。 這就是所謂的閉合并包裹著這些常量和變量,俗稱閉包券腔。
而在這一篇中伏穆,我們可以一步一步看到如何從
reversed = sorted(names, { (s1: String, s2: String) -> Bool in
return s1 > s2
})
利用省略到:
reversed = sorted(names, >)
再利用 trailling closure的特性,可以這樣:
reversed = sorted(names) { $0 > $1 }
閉包當(dāng)然還有更好的例子纷纫,因為我們來看它的一些特性枕扫。
Escaping Closure(逃逸閉包
如果一個閉包被作為一個參數(shù)傳遞給一個函數(shù),并且在函數(shù)return之后才被喚起執(zhí)行辱魁,那么這個閉包是逃逸閉包烟瞧。
好抽象的描述,這篇文章寫得不錯:
不逃逸閉包的生命周期:
Pass a closure into a function
The function runs the closure (or not)
The function returns
然后這個closure就死掉了染簇。
而逃逸閉包則會一直存在参滴,沒有因為function被kill而死掉,所以我們叫這個閉包為逃逸閉包(锻弓?
在以下的兩種情況砾赔,我們需要使用 escaping closure:
異步execution,并不能說函數(shù)return了就把closure kill掉青灼,因為這個closure可能還沒有執(zhí)行完畢
存儲暴心,如果任何全局變量都有一些些存儲存在,那么這個closure也被逃逸掉了杂拨。
在 Swift 1 和 2中酷勺, closure by default 是 escaping的,所以我們需要用 @noescape 來mark.
在 Swift 3中扳躬,closure by default是non-escaping,我們需要用@escaping 來mark
In Swift 3, closure parameters are non-escaping by default; you can use the new @escaping attribute if this isn’t what you want. Non-escaping closures passed in as arguments are guaranteed to not stick around once the function returns.