作用:將表達示包裝為閉包, 目的:選擇性求值
例如,做一個身份驗證的程序技即,驗證規(guī)則如下:
- 指紋掃描通過著洼,身份驗證通過;
- 若指紋掃描不通過則進行面部掃描而叼,
- 面部掃描通過身笤,身份驗證通過;
- 面部掃描不通過葵陵,叫保安液荸;
第一版程序如下:
func openTheDoor(){
print("Identity verified, door is opened!")
}
func callGuard(){
print("Maybe bad guy comes, call the guard!")
}
func verifyidentity(scanFinger:Bool,scanFace:Bool){
if scanFinger {
openTheDoor()
return
}
if scanFace {
openTheDoor()
}else{
callGuard()
}
}
討論:
swift 方法中的表達式都是要求值的,這中間有兩個問題:
- 某些參數(shù)的值的獲取很耗資源脱篙,但某些情況下我們不需要娇钱;
- 某些條件下,某些參數(shù)的獲取不可行绊困。
我們的情況下屬于第二種(這里假定指紋掃描結(jié)果和面部掃描的結(jié)果都需要另外的函數(shù)執(zhí)行并提供結(jié)果文搂,可自行寫一個簡單程序),顯然當指紋掃描已經(jīng)通過了秤朗,毫無必要再進行面部掃描煤蹭,而且很耗資源。怎么辦?一個很自然的想法是硝皂,第二個參數(shù)做成一個閉包(注常挚,閉包的值是明確的,但可以選擇性執(zhí)行)
func verifyidentity(scanFinger:Bool,scanFace:()->Bool){
if scanFinger {
openTheDoor()
return
}
if scanFace() {
openTheDoor()
}else{
callGuard()
}
}
可能的調(diào)用形式是這樣的
verifyidentity(scanFinger(),scanFace:{scanFace()})
顯然稽物,如果 scanFinger()通過了奄毡,scanFace實際上沒有被執(zhí)行。但是姨裸,實在太丑了秧倾。
再進行改良,程序如下:
func verifyidentity(scanFinger:Bool,@autoclosure scanFace:()->Bool){
if scanFinger {
openTheDoor()
return
}
if scanFace() {
openTheDoor()
}else{
callGuard()
}
}
可能的調(diào)用形式是這樣的
verifyidentity(scanFinger(),scanFace:scanFace())
世界清靜了傀缩。
@autoclosure做了什么那先?它把一個形如 para:T
形式的參數(shù)自動包裝成一個para: () -> T
形式的閉包,而其調(diào)用形式不變赡艰。(閉包是否執(zhí)行售淡,當然是看你的程序怎么寫了,于是出現(xiàn)了選擇性執(zhí)行的說法)
什么時機用慷垮?參數(shù)的值可能用不上且其獲取耗費資源或某情況下不可以獲取時揖闸。
一些討論
問題一,能否直接傳入閉包——NO
問題二料身,能被哪些形式重載汤纸?
//1.
func verifyidentity(scanFinger:Bool,@autoclosure scanFace:()->Bool){
}
//2.
func verifyidentity(scanFinger:Bool,scanFace:Bool){
}
//3.
func verifyidentity(scanFinger:Bool,scanFace:()->Bool){
}
居然三種形式函數(shù)在 playground 中寫的時候都可以通過,但在使用的時候報錯芹血。刪除第二種這可以了贮泞,因為1和2在使用時不可區(qū)分。
這里有一個小把戲幔烛,如果你的波函數(shù)有一個@autoclosure的版本啃擦,又有一個接受閉包的版本,就好像這個參數(shù)既可以接受一個普通參數(shù)饿悬,又可以接受一個閉包令蛉。