Swift Closure(閉包)
Closure(閉包)是什麼呢?它就像是一個沒有名稱的函數,也被稱做 匿名函數
。它,無所不在,不管是在底層或第三方的框架中,這代表 Closure 在 Swift 裡是學習重點之一。若在學習初期若還不是對閉包那麼的熟悉,可以把它想像成就只是個方法,可被宣告成 property 或 parameter。列舉兩個在開發時常見的情境:
- 當需要呼叫 API 時,通常會透過一個函數去呼叫它,在這個函數裡總是會使用非同步的方式去呼叫 API,此時就得等待非同步的任務完成時,Callback 回來接著再執行繼續下一個任務。
- 在高階函數裡,總是也會因為要判斷某個值的結果而大量使用。
- closure 被宣告成 property,用來當物件和物件之間的溝通的橋樑。
簡而言之,閉包就是個可被呼叫的函數而已,只是長得較奇怪。而 Swift 中的閉包和 Objective-C 的 blocks 都有異曲同工之妙,而它們的概念也是大同小異的。以下將開始說明什麼是閉包、閉包的應用、使用的時機點等等😀
宣告方式
{ (參數) -> 回傳型別 in 處理邏輯...}
宣告閉包並將其存放在變數中,最後呼叫它
宣告閉包的 Property
將函式存放在變數中並呼叫它
函數也可以被當成參數來傳遞
說穿了 Closure 就是一個 Block,其可以是自行宣告的,也可以是 func 的;也可 Capture 值,也可有回傳值。
範例1:
撰寫一個函式,第一個參數為字串,第二個參數為閉包函式。
呼叫此閉包函式,會得到 “Hello Frank” 的結果。
範例2:
以下開始介紹閉包從最完整到最簡潔的寫法,首先撰寫一個加法功能的閉包函式,並使用最原始的方式來呼叫它,最後會得到結果 15。
根據上下文推測型別(Inferring Type From Context)
通過內聯閉包運算式所構造的閉包作為參數傳遞給函數時,都可以推測出閉包的參數和返回值的型別,所以就可以拿掉「小括號」和「參數型別」。
閉包單行表示式隱含返回(Implicit Return From Single-Expression Closure)
單行運算式閉包可以通過隱藏 return 關鍵字來隱含返回單行運算式的結果。
參數名稱縮寫(Shorthand Argument Names)
在閉包運算式中可以使用參數名稱縮寫,例如第一個參數可以寫成 $0,第二個參數則可以寫成 $1,然而這樣的寫法就也可以一併省略 in 關鍵字。
尾隨閉包(Trailing Closure)
若是閉包函式的閉包參數是在最後一個,可使用尾隨閉包(trailing closure syntax)又稱為語法蜜糖(syntax sugar)來處理,把閉包參數放在最後的大括號即可。
範例3:
開發常用到的 UIViewController present(_:animated:completion:)
let next: NextUIViewController = NextUIViewController()self.present(next, animated: true, completion: {() -> Void in print(“to next…”)})
依 Apple Documentation 所示
當我們呼叫 present(_:animated:completion:) 時,會先執行切換頁數、處理動畫等邏輯,最後再呼叫閉包函式,也就是印出「to next…」的區塊。
範例4:
撰寫類高階函數的 filter 的閉包函式。
使用時機
到底是否要設計帶有 Closure 的 Function 呢?可以站在被呼叫的 Function 需不需要執行 Callback 的動作 來思考這件事
條件若成立,就考慮設計 closure 來處理該邏輯,再來要考慮的項目:
- 是否需要將參數值傳遞給 caller(呼叫者),讓 caller 透過 capture 捕獲得其值?
2. 是否需要取得 caller(呼叫者)的 return 值?
以上條件若是都成立,就得設計一閉包「且」需要將參數值傳遞給 Caller「且」需要取得 Caller 的 Return 值。舉一個 Higher-Order-Fucntions 裡的 filter(_:)來說明,此 Function 的主要用途是可用來過濾出自定義的條件值,這句話已成立以上三個條件,讓我們來看看 Apple 如何定義這個 Function 的 Closure 吧。
#3
將過濾出的元素集合回傳。
#2
取得 Caller(呼叫者)的 Return 值。
#1
將參數值傳遞給 Caller(呼叫者),讓 Caller 透過 Capture(捕捉)的方式捕獲得其值
使用方式如下:
以上,若還是不太懂,可以回頭看看範例 4,相信會更清楚明白些😀
如果您喜歡我的文章,請多按幾下「拍手」給我鼓勵,或是按「follow」讓我持續提供好文章給您。