Closure

66 阅读4分钟

原文链接

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

内容:

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

image.png

在Apple官方的开發资料裡Closure的語法(Closure Expression Syntax)如

image.png

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

image.png

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

image.png

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

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

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

image.png

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

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

image.png

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

簡化說明『Trailing Closures## 』:

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

image.png

image.png

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

image.png

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

image.png

簡化說明『Inferring Type From Context』:

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

image.png

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

image.png

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

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

image.png

簡化說明 『Shorthand Argument Names』:

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

image.png

簡化說明『Operator Methods』:

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

image.png

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

image.png

相關參考資料如下:

docs.swift.org/swift-book/…