Swift 學習之閉包 Closures

2021-06-27 19:34:48 字數 4760 閱讀 2292

swift 學習之閉包(closures)

/** 閉包 closures

1. 閉包概念

閉包是功能性自包含模組,可以在**中被傳遞和使用。 swift 中的閉包與 c 和 objective-c 中的 blocks 以及其他一些程式語言中的 lambdas 比較相似。

閉包可以捕獲和儲存其所在上下文中任意常量和變數的引用。

這就是所謂的閉合幷包裹著這些常量和變數,俗稱閉包。

swift 會為您管理在捕獲過程中涉及到的記憶體操作。

在函式章節中介紹的全域性和巢狀函式實際上也是特殊的閉包,

閉包採取如下三種形式之一:

1. 全域性函式是乙個有名字但不會捕獲任何值的閉包

2. 巢狀函式是乙個有名字並可以捕獲其封閉函式域內值的閉包

3. 閉包表示式是乙個利用輕量級語法所寫的可以捕獲其上下文中變數或常量值的沒有名字的閉包

swift 的閉包表示式擁有簡潔的風格,並鼓勵在常見場景中以實現語法優化,主要優化如下:

* 利用上下文推斷引數和返回值型別

* 單表示式(single-expression)閉包可以省略 return 關鍵字 * 引數名稱簡寫

* trailing 閉包語法

2. 閉包表示式

巢狀函式是一種在較複雜函式中方便進行命名和定義自包含**模組的方式。

當然,有時 候撰寫小巧的沒有完整定義和命名的類函式結構也是很有用處的,

尤其是在處理一些函式並需要將另外一些函式作為該函式的引數時。

閉包表示式是一種利用簡潔語法構建內聯閉包的方式。

閉包表示式提供了一些語法優化, 使得撰寫閉包變得簡單明瞭。

*/// 3.sorted 排序函式

// 3.1 函式閉包排序

// 定義陣列

var personname : [string] = ["lili","kaiti","anna","bobo","dali"]

// 定義排序函式

func sortname (s1 :string, s2 :string) ->bool

personname = sorted(personname,sortname) // sorted(,) 第乙個引數為陣列,第二個引數為排序的方式函式

println(personname) // 列印: [lili, kaiti, dali, bobo, anna] 從大到小排序

// 3.2 閉包表示式語法

/* 閉包排序 */

personname = sorted(personname,)

println(personname) // 列印: [anna, bobo, dali, kaiti, lili] 從小到大排序

// 3.3 根據上下文推斷型別,

/* 省略引數的型別 */

personname = sorted(personname,) // 省略引數型別

println(personname) // 列印: [lili, kaiti, dali, bobo, anna] 從大到小排序

// 3.4

/* 單行表示式閉包可以省略 return */

personname = sorted(personname,) // 省略return

println(personname) // 列印: [anna, bobo, dali, kaiti, lili] 從小到大排序

// 3.5 引數名簡寫

/* swift 自動為內聯函式提供了引數名稱簡寫功能,您可以直接通過 $0,$1,$2 等名字來引用 的閉包的引數的值。*/

personname = sorted(personname,) // 省略引數,用$0 和$1 表示

println(personname) // 列印: [anna, bobo, dali, kaiti, lili] 從小到大排序

// 3.6 運算子函式

/*swift 的 string 型別定義

了關於大於號 (>) 的字串實現,讓其作為乙個函式接受兩個 string 型別的引數並返回 bool 型別的值。

而這正好與 sort 函式的第二個引數需要的函式型別相符合。

因此,可以簡單地傳遞乙個大於號,swift 可以自動推斷出您想使用大於號的字串函式實現:

*/personname = sorted(personname, >) // 省略引數,用$0 和$1 表示

println(personname) // 列印: [lili, kaiti, dali, bobo, anna] 從大到小排序

// 4. trailing(掛尾) 閉包

/*如果您需要將乙個很長的閉包表示式作為最後乙個引數傳遞給函式,可以使用 trailing 閉包

來增強函式的可讀性

*/// 4.1 排序例子,轉換為 trailing(掛尾) 閉包

personname = sorted(personname) // 將閉包{}的內容寫在sorted外部

println(personname) // 列印: [anna, bobo, dali, kaiti, lili] 從小到大排序

/*當閉包非常長以至於不能在一行中進行書寫時,trailing 閉包就變得非常有用

注意:如果函式只需要閉包表示式乙個引數,當您使用 trailing 閉包時,您甚至可以把

() 省略掉。

*/// 4.2 trailing(掛尾)閉包 例項2

// 將數字用中文數輸出

/*當閉包非常長以至於不能在一行中進行書寫時,trailing 閉包就變得非常有用。

舉例來說,swift 的 array 型別有乙個 map 方法,其獲取乙個閉包表示式作為其唯一引數。

陣列中的每乙個元素呼叫一次該閉包函式,並返回該元素所對映的值(也可以是不同型別的值)。

具體的對映方式和返回值型別由閉包來指定。

當提供供給陣列閉包函式後,map 方法將返回乙個新的陣列,陣列中包含了與原陣列一一對

應的對映後的值

*/var num = [10,21,43,56,78,99]

var dict = [

0:"零",

1:"一",

2:"二",

3:"三",

4:"四",

5:"五",

6:"六",

7:"七",

8:"八",

9:"九"

]let strings = num.map

return output

}println(strings) // 列印: [一零, 二一, 四三, 五六, 七八, 九九]

/*注意:

字典 下標後跟著乙個嘆號 (!),因為字典下標返回乙個可選值 (optional value),

表明即使該 key 不存在也不會查詢失敗。

在上例中,它保證了 number % 10 可以總是作為乙個 digitnames 字典的有效下標 key。

因此嘆號可以用於強展開 (force-unwrap) 儲存在可選下標項中的 string 型別值。

*/// 5. 捕獲 (caputure)

/*閉包可以在其定義的上下文中捕獲常量或變數。

即使定義這些常量和變數的原作用域已經 不存在,閉包仍然可以在閉包函式體內引用和修改這些值。

swift 最簡單的閉包形式是巢狀函式,也就是定義在其他函式體內的函式。

巢狀函式可以捕 獲其外部函式所有的引數以及定義的常量和變數。

*/func repeatadd(#num1 :int) ->() ->int

return add

}let total = repeatadd(num1 : 5)

println(total()) // 列印: 5

println(total()) // 列印: 10

println(total()) // 列印: 15

println(total()) // 列印: 20

/*注意:swift 會決定捕獲引用還是拷貝值。

您不需要標註 num1 或者 totalnum 來宣告 在嵌入的 add 函式中的使用方式。

swift 同時也處理 runingtotal 變數的記憶體 管理操作,如果不再被 incrementor 函式使用,則會被清除。

*/let total2 = repeatadd(num1 : 2)

println(total2()) // 列印: 2

println(total2()) // 列印: 4

println(total2()) // 列印: 6

println(total2()) // 列印: 8

/* 注意:

如果您閉包分配給乙個類例項的屬性,並且該閉包通過指向該例項或其成員來捕獲了 該例項,

您將建立乙個在閉包和例項間的強引用環。

swift 使用捕獲列表來打破這種強 引用環

*/// 6. 閉包是引用型別

/*上面的例子中,total1 和 total2 是常量,但是這些常量指向的閉包

仍然可以增加其捕獲的變數值。

這是因為函式和閉包都是引用型別。

這也意味著如果您將閉包賦值給了兩個不同的常量/變數,兩個值都會指向同乙個閉包:

*/let total3 = total // 將total 賦值給 total3, 引用型別 total3 的指標指向 total

println(total3()) // 列印: 25 total 再次相加

swift學習之閉包(closure)

swift的閉包和c,oc中block是差不多的,其實swift中的全域性和巢狀函式實際上也是一種特殊的閉包,閉包有三種形式 1 全域性函式是有乙個名字,但不能捕獲任何值的閉包 2 巢狀函式是有乙個名字,可以捕獲在函式內的值得閉包 3 閉包表示式是乙個輕量級的語法,可以從上下文中捕獲值 閉包表達是乙...

Swift學習之閉包Closures

原始碼位址 let learnios learnios 引數lan,in將引數與函式體隔開 let learn learn swift return為一行時可省了return let learn1 let result learn1 swiftui print result func findwor...

swift 學習《五》 閉包

函式 格式 引數列表 對外名內部使用名 引數型別,對外名內部使用名 引數型別 閉包格式 宣告乙個引數是閉包的函式 func 函式名 閉包名 引數名 引數型別 引數名 引數型別 返回值 呼叫 引數中帶閉包的函式 函式名 1,尾隨引數,沒有值的括號可省,沒有返回值是,in 都課省 2,in 的作用是,分...