『Swift 5學習系列』-11. 閉包(Closures)

Shin Chao
彼得潘的 Swift iOS App 開發教室
7 min readMay 19, 2018

--

閉包(Closure)因該是開發IOS必須一定要了解的,然而什麼是Closure呢?其實Closure與Function的功能很像,簡單來說你可以將Closure當作一個沒有名稱的Function,也就是一個匿名函式所以Closure一樣可以定義一段程式碼的區塊,也可以接受參數與回傳資料,然而Closure與Function的差異在哪呢?

在Apple官方的開發資料裡Closure的語法(Closure Expression Syntax)如下:

看到這邊,你還是可能不知道什麼是Closure的語法?其實如果用從Function的角度轉換成Closure的方式來說明,你可能很快就能了解基本的Closure語法。

你可能看出來了,其實移除Function的func 與名稱,再將參數與回傳型別移到大括號內,並在回傳型別後加一個in,表示開始程式區塊部分,就完成了。這樣你在看在Apple官方的開發資料裡Closure的語法,相信你因該就能了解。

了解基本的Closure的語法之後,就要知道Closure如何使用了。因為Closure無法像Function一樣單獨定義,所以必須是指派給變數或是常數,或是當作參數傳入Function,下面將用範例說明一下。

範例(將Closure指派給常數):

將Closure指派給變數或是常數,其實跟Function指派給變數或是常數一樣,所以呼叫時也需要加上( )。

範例(將Closure當作參數傳入Function):

Function可以當參數傳入Function,因此也可以將Closure當作參數傳入Function,一般來說是沒有重複呼叫的需求時就傳入Closure,通常是在執行完某個 func之 後,馬上要處理某件事情時使用,例如從網路下載資料完,要馬上處理與顯示畫面時。

相信各位因該了解了Closure的語法,也知道如何使用Closure了,但是你一定還是要學會如何簡化Closure,你或許覺得奇怪為什麼還要學會簡化呢?因為不論是其他開發者寫的API或是IOS提供的許多API都是用簡化的方式寫的,所以必須了解如何如何簡化,不然看到簡化的Closure就會一頭霧水了,看不懂別人為什麼可以這樣寫了,那接下來就要說明如何簡化Closure了。

簡化說明『Trailing Closures』:

當Closure是Function的最後一個參數時,可以移除function中closure「參數」與「冒號」,並將原先最後面的「小括號」移到前面。

其實在Xocde中的自動完成輸入時就會自動省略。

然而當參數只有一個Closure時,其實就是等於Trailing closure一樣。

簡化說明『Inferring Type From Context』:

Inferring Type From Context簡單來說,就是Closure的參數型別與返回值型別的省略,因為Closure作為參數傳遞給function時,Swift從function知道Closure的參數型別與返回值型別,所以可以省略Closure的參數型別與返回值型別。

當Closure的參數型別省略時,包含參數的「小括號」也可以省略。

簡化說明『Implicit Returns from Single-Expression Closures』:

Implicit Returns from Single-Expression Closures簡單來說,就是Closure內只有一行程式,則可以不寫「return」。

簡化說明『Shorthand Argument Names』:

Shorthand Argument Names簡單來說,就是Closure參數的名稱變成預設代號,第一個參數為 $0,第二個參數為 $1,依此類推。因為透過$存取參數,所以原先宣告參數也沒有存在的必要,因此這樣的寫法就也可以一併省略 in。

簡化說明『Operator Methods』:

Operator Methods簡單來說,就是加、減、乘、除等等..(operator)可以當做Closure傳入Function,因為operator都是由Function定義。

如果想在function外繼續使用傳入Closure內的參數,那就需要Closure的參數上加上@escape,因為當Closure作為參數傳入function時,則這個Closure的生命週期因該在該function返回時也跟著結束,所以必須需要加上@escape,讓Closure傳入的參數能在function返回後,一樣能執行。如果Closure的參數上加上@escape,那在存取⾃己的屬性要加上self。有一點要注意的是Optional的Closure參數則預設就是為@escape。

--

--