欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入理解Swift語言中的閉包機(jī)制

 更新時間:2015年11月03日 16:40:04   投稿:goldensun  
這篇文章主要介紹了Swift語言中的閉包機(jī)制,是Swift入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下

在 Swift 中的閉包類似于結(jié)構(gòu)塊,并可以在任何地方調(diào)用,它就像 C 和 Objective C 語言內(nèi)置的函數(shù)。 函數(shù)內(nèi)部定義的常數(shù)和變量引用可被捕獲并存儲在閉包。函數(shù)被視為封閉的特殊情況,它有 3 種形式。

2015113163239975.png (562×76)

在 Swift 語言閉合表達(dá)式,如下優(yōu)化,重量輕語法風(fēng)格,其中包括:

  • 推導(dǎo)參數(shù)并從上下文菜單返回值的類型
  • 從單封表達(dá)的隱性返回
  • 簡略參數(shù)名稱
  • 尾部閉包語法

語法
下面是一個通用的語法定義用于閉包,它接受參數(shù)并返回數(shù)據(jù)的類型:

復(fù)制代碼 代碼如下:
 
{(parameters) -> return type in
   statements
}
 
下面是一個簡單的例子:
復(fù)制代碼 代碼如下:
 
let studname = { println("Welcome to Swift Closures") }
studname()
 
當(dāng)我們使用 playground 運(yùn)行上面的程序,我們得到以下結(jié)果

Welcome to Swift Closures

以下閉包接受兩個參數(shù)并返回一個布爾值:

復(fù)制代碼 代碼如下:
 
{(Int, Int) -> Bool in
   Statement1
   Statement 2
    ---
   Statement n
}
 
下面是一個簡單的例子:
復(fù)制代碼 代碼如下:
 
let divide = {(val1: Int, val2: Int) -> Int in
   return val1 / val2
}
let result = divide(200, 20)
println (result)
 
當(dāng)我們使用 playground 運(yùn)行上面的程序,我們得到以下結(jié)果

10

在閉包中的表達(dá)式
以便捷的方式命名來定義代碼塊可以通過嵌套函數(shù)實(shí)現(xiàn)的。取而代之代表整個函數(shù)聲明及名稱構(gòu)造用來表示函數(shù)。代表函數(shù)的語法清晰,簡短聲明是通過封閉的表達(dá)來實(shí)現(xiàn)的。

升序排列程序
排序字符串是 Swift 中保留的函數(shù) “sorted”,這是在標(biāo)準(zhǔn)庫中已提供實(shí)現(xiàn)。該函數(shù)將所述給定的字符串進(jìn)行遞增順序排序并返回具有相同的尺寸,并在舊數(shù)組中相同數(shù)據(jù)類型的一個新的數(shù)組的元素。舊的數(shù)組保持不變。

兩個參數(shù)的排序在函數(shù)內(nèi)部表示:

已知類型的值表示為數(shù)組

數(shù)組的內(nèi)容 (Int,Int) ,并返回一個布爾值(Bool),如果數(shù)組排序不好就會返回true,否則將返回false。

普通函數(shù)帶輸入字符串被寫入,并傳遞給排序函數(shù)獲得字符到新的數(shù)組,如下面所示:

復(fù)制代碼 代碼如下:
 
func ascend(s1: String, s2: String) -> Bool {
   return s1 > s2
}
let stringcmp = ascend("swift", "great")
println (stringcmp)
 
當(dāng)我們使用 playground 運(yùn)行上面的程序,我們得到以下結(jié)果

復(fù)制代碼 代碼如下:

true

最初的數(shù)組排序給定為 "Swift" 和 "great"。函數(shù)用來數(shù)組排序被聲明為字符串?dāng)?shù)據(jù)類型,并且返回類型為布爾型。 兩個字符串進(jìn)行比較,并以升序排序,并存儲在新的數(shù)組。如果排序執(zhí)行成功,該函數(shù)將返回true;否則將返回 false。

閉包表達(dá)式語法用法

常量參數(shù):

可變參數(shù) 和 inout 參數(shù)

閉包表達(dá)不支持的默認(rèn)值??勺儏?shù)和參數(shù)元組也可以用來作為參數(shù)類型和返回類型。

復(fù)制代碼 代碼如下:
 
let sum = {(no1: Int, no2: Int) -> Int in
   return no1 + no2
}
let digits = sum(10, 20)
println(digits)
 
當(dāng)我們使用 playground 運(yùn)行上面的程序,我們得到以下結(jié)果

30

在函數(shù)聲明中提到的參數(shù)和返回類型聲明,也可通過使用 'in' 關(guān)鍵字內(nèi)聯(lián)閉包表達(dá)式函數(shù)表示。 一旦聲明參數(shù)及其返回類型“in”關(guān)鍵字,則用于表示閉包體。

單一表達(dá)式隱式返回
在這里,排序函數(shù)的第二個參數(shù)的函數(shù)類型明確指出,一個布爾值必須由閉包返回。因?yàn)殚]包體內(nèi)含有一個表達(dá)式(s1 > s2)返回一個布爾值, 不會出現(xiàn)歧義,其返回關(guān)鍵字可以省略。

要返回一個表達(dá)式語句在閉包中, “return” 關(guān)鍵字在其聲明部分被省略。

復(fù)制代碼 代碼如下:
 
let count = [5, 10, -6, 75, 20]
var descending = sorted(count, { n1, n2 in n1 > n2 })
var ascending = sorted(count, { n1, n2 in n1 < n2 })

println(descending)
println(ascending)

 
當(dāng)我們使用 playground 運(yùn)行上面的程序,我們得到以下結(jié)果

[75, 20, 10, 5, -6]
[-6, 5, 10, 20, 75]

該語句本身明確規(guī)定,當(dāng) string1 大于 string2 返回 true,否則為false,因此return語句省略。

已知類型的閉包
考慮兩個數(shù)相加。我們知道相加后將返回整數(shù)數(shù)據(jù)類型。因此,已知類型的閉包聲明

復(fù)制代碼 代碼如下:
 
let sub = {(no1: Int, no2: Int) -> Int in
   return no1 - no2
}
let digits = sub(10, 20)
println(digits)
 
當(dāng)我們使用 playground 運(yùn)行上面的程序,我們得到以下結(jié)果

-10

聲明簡寫參數(shù)名稱作為閉包
Swift 自動提供簡寫參數(shù)名內(nèi)聯(lián)閉包, 可以使用由 $0,$1,$2 等等名稱,指的是封閉的參數(shù)值。

復(fù)制代碼 代碼如下:
 
var shorthand: (String, String) -> String
shorthand = { $1 }
println(shorthand("100", "200"))
 
在這里,$0 和 $1 參考閉包的第一和第二個字符串參數(shù)。

當(dāng)我們使用 playground 運(yùn)行上面的程序,我們得到以下結(jié)果

200

Swift 方便用戶來表示內(nèi)嵌閉包為縮寫參數(shù)名為:$0, $1, $2 --- $n.

閉包參數(shù)列表中被省略定義部分,當(dāng)我們表示內(nèi)部閉包表達(dá)式簡寫參數(shù)名。 根據(jù)函數(shù)類型簡寫參數(shù)名稱將被導(dǎo)出。由于簡寫參數(shù)表達(dá)體所定義的 'in' 關(guān)鍵字被省略。

閉包作為操作函數(shù)
Swift 提供了一種簡單的方法訪問的成員,只需提供操作符函數(shù)作為閉包。 在前面的例子關(guān)鍵字“Bool”是用來比較兩個字符串,相等返回“true”,否則返回“false”。

表達(dá)式即使在閉包中變得簡單在操作函數(shù):

復(fù)制代碼 代碼如下:
 
let numb = [98, -20, -30, 42, 18, 35]
var sortedNumbers = numb.sorted({
   (left: Int, right: Int) -> Bool in
      return left < right
})
let asc = numb.sorted(<)
println(asc)
 
當(dāng)我們使用 playground 運(yùn)行上面的程序,我們得到以下結(jié)果

[-30, -20, 18, 35, 42, 98]


閉包作為尾隨包
傳遞這個函數(shù)的最后一個參數(shù)到閉合表達(dá)式使用“尾隨閉包”聲明。它使用 {} 寫在函數(shù)()外部。當(dāng)它不能寫入函數(shù)內(nèi)聯(lián)在一行上,使用它是需要。

復(fù)制代碼 代碼如下:
 
reversed = sorted(names) { $0 > $1}
 
其中 {$0 > $1} 表示為外部(名稱)聲明尾隨閉包。
復(fù)制代碼 代碼如下:
 
import Foundation
var letters = ["North", "East", "West", "South"]
 
let twoletters = letters.map({ (state: String) -> String in
   return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString
})
let stletters = letters.map() { $0.substringToIndex(advance($0.startIndex, 2)).uppercaseString }
println(stletters)
 
當(dāng)我們使用 playground 運(yùn)行上面的程序,我們得到以下結(jié)果

[NO, EA, WE, SO]

捕獲值和引用類型
在閉包的幫助下 Swift 完成捕捉常量和變量的值。它還參考修改值,即使常量和變量在閉包體已經(jīng)不存。

捕獲常數(shù)和變量值是通過使用嵌套函數(shù)寫入函數(shù),這是使用其它函數(shù)體來實(shí)現(xiàn)的:

  • 一個嵌套函數(shù)捕獲
  • 外部函數(shù)參數(shù)
  • 捕捉常量和外部函數(shù)中定義的變量

Swift 中當(dāng)常量或變量在函數(shù)中聲明,引用到變量也自動地被閉合創(chuàng)建。它也提供工具來引用兩個以上的變量作為同一閉合如下:

復(fù)制代碼 代碼如下:
 
let decrem = calcDecrement(forDecrement: 18)
decrem()
 
在這里,oneDecrement 和 遞減變量都指向同一個內(nèi)存塊閉合參考。
復(fù)制代碼 代碼如下:
 
 func calcDecrement(forDecrement total: Int) -> () -> Int {
   var overallDecrement = 100
   func decrementer() -> Int {
      overallDecrement -= total
      println(overallDecrement)
      return overallDecrement
   }
   return decrementer
}
let decrem = calcDecrement(forDecrement: 18)
decrem()
decrem()
decrem()
 
當(dāng)我們使用 playground 運(yùn)行上面的程序,我們得到以下結(jié)果:

82
64
46

當(dāng)每一個外部函數(shù) calcDecrement 調(diào)用時都會調(diào)用 decrementer()函數(shù) 并通過值 18 遞減,并在外部函數(shù) calcDecrement 的幫助下返回結(jié)果。在這里,calcDecrement 作為一個閉合。

即使函數(shù) decrement()沒有任何參數(shù),閉合默認(rèn)情況下是指變量的"整體遞減“ “total” 通過獲取其值。為指定的變量的值副本被使用新的 decrementer()函數(shù)存儲。Swift 通過處理存儲器管理功能分配和釋放存儲器空間當(dāng)變量在不使用。


下面來一波總結(jié)~

復(fù)制代碼 代碼如下:

/* 閉包(Closures)
 * 閉包是自包含的功能代碼塊,可以在代碼中使用或者用來作為參數(shù)傳值。
 * 在Swift中的閉包與C、OC中的blocks和其它編程語言(如Python)中的lambdas類似。
 * 閉包可以捕獲和存儲上下文中定義的的任何常量和變量的引用。這就是所謂的變量和變量的自封閉,
 * 因此命名為”閉包“("Closures)").Swift還會處理所有捕獲的引用的內(nèi)存管理。
 *
 * 全局函數(shù)和嵌套函數(shù)其實(shí)就是特殊的閉包。
 * 閉包的形式有:
 * (1)全局函數(shù)都是閉包,有名字但不能捕獲任何值。
 * (2)嵌套函數(shù)都是閉包,且有名字,也能捕獲封閉函數(shù)內(nèi)的值。
 * (3)閉包表達(dá)式都是無名閉包,使用輕量級語法,可以根據(jù)上下文環(huán)境捕獲值。
 *
 * Swift中的閉包有很多優(yōu)化的地方:
 * (1)根據(jù)上下文推斷參數(shù)和返回值類型
 * (2)從單行表達(dá)式閉包中隱式返回(也就是閉包體只有一行代碼,可以省略return)
 * (3)可以使用簡化參數(shù)名,如$0, $1(從0開始,表示第i個參數(shù)...)
 * (4)提供了尾隨閉包語法(Trailing closure syntax)
 */
 
 // 下面用Swift標(biāo)準(zhǔn)庫中的sort方法來一步步簡化閉包寫法
 // sort函數(shù)需要兩個參數(shù)
 // 參數(shù)一:數(shù)組
 // 參數(shù)二:一個閉包:帶有兩個參數(shù),這兩個參數(shù)類型與數(shù)組中的元素類型相同,返回值是Bool
 var names = ["Swift", "Arial", "Soga", "Donary"]
 
 // 第一種方式:使用函數(shù)
 func backwards(firstString: String, secondString: String) -> Bool {
   return firstString > secondString // 升序排序
 }
 // 這里第二個參數(shù),傳了一個函數(shù)
 // reversed is equal to ["Swift", "Soga", "Donary", "Arial"]
 var reversed = sort(nams, backwards)
 
 // 第二種方式:使用閉包方式
 // 完整閉包寫法是在花括號內(nèi)有參數(shù)列表和返回值,用關(guān)鍵字in表明閉包體的開始
 // (firstString: String, secondString: String) 閉包參數(shù)列表
 // -> Bool 指明閉包返回值類型是Bool
 // in關(guān)鍵字表明閉包體的開始
 reversed = sort(names, { (firstString: String, secondString: String) -> Bool in
    return firstString > secondString
 })

 // 這里可以進(jìn)一步簡化寫法,因?yàn)殚]包代碼比較短,可以寫到一行上
 reversed = sort(names, { (firstString: String, secondString: String) -> Bool in return firstString > secondString})
 
// 下面再進(jìn)一步簡化寫法 :根據(jù)環(huán)境上下文自動推斷出類型
// 參數(shù)列表都沒有指明類型,也沒有指明返回值類型,這是因?yàn)閟wift可以根據(jù)上下文推測出
// firstString和secondString的類型會是names數(shù)組元素的類型,而返回值類型會根據(jù)return語句結(jié)果得到
reversed = sort(names, { firstString, secondString in return firstString > secondString})

// 再進(jìn)一步簡化:隱式返回(單行語句閉包)
// 因?yàn)殚]包體只有一行代碼,可以省略return
reversed = sort(names, { firstString, secondString in firstString > secondString})

// 再進(jìn)一步簡化:使用簡化參數(shù)名($i,i=0,1,2...從0開始的)
// Swift會推斷出閉包需要兩個參數(shù),類型與names數(shù)組元素相同
reversed = sort(names, { $0 > $1 }) 

// 最簡單的一種寫法:使用操作符
reversed = sort(names, >) 
 
 
/*
 * 尾隨閉包(Trailing Closures)
 * 如果函數(shù)需要一個閉包參數(shù)作為參數(shù),且這個參數(shù)是最后一個參數(shù),而這個閉包表達(dá)式又很長時,
 * 使用尾隨閉包是很有用的。尾隨閉包可以放在函數(shù)參數(shù)列表外,也就是括號外。如果函數(shù)只有一個參數(shù),
 * 那么可以把括號()省略掉,后面直接跟著閉包。
 */
// Array的方法map()就需要一個閉包作為參數(shù)
let strings = numbers.map { // map函數(shù)后面的()可以省略掉
  (var number) -> String in
  var output = ""
  while number > 0 {
    output = String(number % 10) + output
 number /= 10
  }
  return output
}
 
/* 捕獲值
 * 閉包可以根據(jù)環(huán)境上下文捕獲到定義的常量和變量。閉包可以引用和修改這些捕獲到的常量和變量,
 * 就算在原來的范圍內(nèi)定義為常量或者變量已經(jīng)不再存在(很牛逼)。
 * 在Swift中閉包的最簡單形式是嵌套函數(shù)。
 */
func increment(#amount: Int) -> (() -> Int) {
  var total = 0
  func incrementAmount() -> Int {
    total += amount // total是外部函數(shù)體內(nèi)的變量,這里是可以捕獲到的
 return total
  }
  return incrementAmount // 返回的是一個嵌套函數(shù)(閉包)

 
// 閉包是引用類型,所以incrementByTen聲明為常量也可以修改total
let incrementByTen = increment(amount: 10)
incrementByTen() // return 10,incrementByTen是一個閉包
// 這里是沒有改變對increment的引用,所以會保存之前的值
incrementByTen() // return 20 
incrementByTen() // return 30 

let incrementByOne = increment(amount: 1)
incrementByOne() // return 1
incrementByOne() // return 2 
incrementByTen() // return 40
incrementByOne() // return 3

 
 
 

相關(guān)文章

  • Swift中風(fēng)味各異的類型擦除實(shí)例詳解

    Swift中風(fēng)味各異的類型擦除實(shí)例詳解

    你也許曾聽過類型擦除,甚至也使用過標(biāo)準(zhǔn)庫提供的類型擦除類型如 AnySequence,下面這篇文章主要給大家介紹了關(guān)于Swift中風(fēng)味各異的類型擦除的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • Swift用final關(guān)鍵字來防止重寫

    Swift用final關(guān)鍵字來防止重寫

    final關(guān)鍵字在大多數(shù)的編程語言中都存在,表示不允許對其修飾的內(nèi)容進(jìn)行繼承或者重新操作。下面通過實(shí)例代碼給大家介紹swift用final關(guān)鍵字來防止重寫
    2016-12-12
  • Swift中添加雙擊手勢識別器

    Swift中添加雙擊手勢識別器

    在這次IOS應(yīng)用開發(fā)教程中,我們打算實(shí)現(xiàn)手勢識別。正如你所知道的,IOS支持大量的手勢操作,它們能提供了很好的應(yīng)用控制和出色用戶體驗(yàn)。
    2019-08-08
  • Swift實(shí)現(xiàn)表格視圖單元格單選(2)

    Swift實(shí)現(xiàn)表格視圖單元格單選(2)

    這篇文章主要為大家詳細(xì)介紹了Swift實(shí)現(xiàn)表格視圖單元格單選的第二篇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Swift利用純代碼實(shí)現(xiàn)時鐘效果實(shí)例代碼

    Swift利用純代碼實(shí)現(xiàn)時鐘效果實(shí)例代碼

    這篇文章主要給大家介紹了關(guān)于Swift利用純代碼實(shí)現(xiàn)時鐘效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用swift具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • Swift 數(shù)組及常用方法詳解總結(jié)

    Swift 數(shù)組及常用方法詳解總結(jié)

    數(shù)組(Array)是有序的元素序列。 若將有限個類型相同的變量的集合命名,那么這個名稱為數(shù)組名。組成數(shù)組的各個變量稱為數(shù)組的分量,也稱為數(shù)組的元素,有時也稱為下標(biāo)變量
    2021-11-11
  • switch多選擇結(jié)構(gòu)、循環(huán)結(jié)構(gòu)示例詳解

    switch多選擇結(jié)構(gòu)、循環(huán)結(jié)構(gòu)示例詳解

    這篇文章主要介紹了switch多選擇結(jié)構(gòu)、循環(huán)結(jié)構(gòu),本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • 用Swift構(gòu)建一個簡單的iOS郵件應(yīng)用的方法

    用Swift構(gòu)建一個簡單的iOS郵件應(yīng)用的方法

    這篇文章主要介紹了用Swift構(gòu)建一個簡單的iOS郵件應(yīng)用的方法,包括查看和標(biāo)記已讀等基本的郵件應(yīng)用功能,需要的朋友可以參考下
    2015-07-07
  • Swift實(shí)現(xiàn)代碼混淆詳解

    Swift實(shí)現(xiàn)代碼混淆詳解

    本文詳細(xì)講解了Swift實(shí)現(xiàn)代碼混淆的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧<BR>
    2021-11-11
  • SwiftUI?引導(dǎo)頁界面實(shí)現(xiàn)示例

    SwiftUI?引導(dǎo)頁界面實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了SwiftUI?引導(dǎo)頁界面實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09

最新評論