《Swift學(xué)習(xí)筆記》10 - 閉包的簡(jiǎn)單介紹

介紹:Swift 語言由蘋果公司在 2014 年推出新思,用來撰寫 Mac OS 和 iOS 應(yīng)用程序,并且Swift還是開源的笋敞,開源地址:https://github.com/apple/swift,同時(shí)附上官方博客地址:https://swift.org
目前Swift已經(jīng)發(fā)展到了第五版本。顯然蘋果大有推翻 OC “江山”的意思.
今天就來初探一下Swift君旦,看看究竟為何swift有這么大的能力。
參考內(nèi)容:
Swift中文
YungFan老師

swift
一嘲碱、閉包的介紹
  1. 閉包的含義
  • 閉包是匿名函數(shù)

  • 閉包是可以被傳遞和引用的一個(gè)獨(dú)立模塊

  • 閉包能夠捕獲和存儲(chǔ)定義在其上下文中的任何常量和變量的引用金砍,這也就是所謂的閉合并包裹那些常量和變量,因此被稱為“閉包”

  • 閉包和函數(shù)一樣都是引用類型

  • 實(shí)際上 函數(shù)內(nèi)聯(lián)函數(shù)都是特殊的閉包麦锯。

    • 全局函數(shù)是一個(gè)有名字但不會(huì)捕獲任何值的閉包恕稠;
    • 內(nèi)嵌函數(shù)是一個(gè)有名字且能從其上層函數(shù)捕獲值的閉包;
    • 閉包表達(dá)式是一個(gè)輕量級(jí)語法所寫的可以捕獲其上下文中常量或變量值的沒有名字的閉包离咐。
  1. 閉包的書寫
// 基本書寫方式
 { (parameters) -> (return type) in
    statements
  }

// 案例
{
    (閉包的形式參數(shù): String) -> String in
    return 閉包的形式參數(shù)
}
  • 閉包表達(dá)式由一對(duì){}開始與結(jié)束
  • in關(guān)鍵字將閉包分割成兩部分:參數(shù)與返回值谱俭、閉包體
  • 閉包參數(shù)函數(shù)參數(shù)的區(qū)別
    • 形式參數(shù)不能提供默認(rèn)值,其他和函數(shù)一樣宵蛀,閉包表達(dá)式語法能夠使用常量形式參數(shù)昆著、變量形式參數(shù)輸入輸出形式參數(shù),但不能提供默認(rèn)值术陶。可變形式參數(shù)也能使用凑懂,但需要在形式參數(shù)列表的最后面使用元組也可被用來作為形式參數(shù)返回類型梧宫。
二接谨、閉包主要知識(shí)點(diǎn)
  1. 參數(shù)名稱縮寫
  • 參數(shù)類型可以通過函數(shù)類型進(jìn)行推斷:因排序閉包為實(shí)際參數(shù)來傳遞給函數(shù),故 Swift 能推斷它的形式參數(shù)類型和返回類型塘匣。
  • 在單行閉包的時(shí)候,return 關(guān)鍵字可以省略
  • 參數(shù)名稱省略以后脓豪,in 關(guān)鍵字也可以被省略

閉包的正常使用

//從數(shù)組中篩選指出合適的數(shù)據(jù)組成新的數(shù)組
let block = {
    (oneNum : Int) -> Bool in
    return oneNum > 10
}

print(block(11)) // true

第一種簡(jiǎn)寫方法:通過類型推倒
返回箭頭 ( ->)圍繞在形式參數(shù)名周圍的括號(hào)()都可以省略

let blockTwo = {oneNum in return oneNum>10}
print(blockTwo(3)) // false

第二種:閉包的隱式返回 ,省略return關(guān)鍵字

let blockThree = {numOne in numOne>10}
print(blockThree(12)) // true

第三種簡(jiǎn)寫:參數(shù)名稱縮寫忌卤,省略參數(shù)聲明和in扫夜,改為$0
Swift 自動(dòng)對(duì)行內(nèi)閉包提供簡(jiǎn)寫實(shí)際參數(shù)名,你也可以通過 0 ,1 , $2 等名字來引用閉包的實(shí)際參數(shù)值驰徊。
in關(guān)鍵字也能被省略笤闯,因?yàn)殚]包表達(dá)式完全由它的函數(shù)體組成.

let blockFour = {$0>10}
print(blockFour(8)) // false

可以看到 $0代替了 上面的numOne,并且可以in給隱藏了

三棍厂、尾隨閉包
如果你需要將一個(gè)閉包表達(dá)式作為函數(shù)最后一個(gè)實(shí)際參數(shù)傳遞給函數(shù)颗味,使用尾隨閉包將增強(qiáng)函數(shù)的可讀性。尾隨閉包是一個(gè)被書寫在函數(shù)形式參數(shù)的括號(hào)外面(后面)的閉包表達(dá)式:

func doSomething(name: String, block:(_:String)->Void){
    block("尾隨閉包 name=" + name)
}

let age = "24"

doSomething(name: "Swift") { (age) in
    print(age)
}

doSomething(name: "Swift", block: {s in print(s)})

四牺弹、捕獲值

  • 閉包的一個(gè)重要特點(diǎn)就是捕獲上下文已被定義的常量和變量浦马,并放到自己的作用域去使用时呀。
    下面這個(gè)例子說明:
    前面說過函數(shù)也是一種閉包;這是一個(gè)內(nèi)嵌函數(shù)捐韩,里面的函數(shù)incrementor可以捕獲到主函數(shù)的一些參數(shù)runningTotalamount
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}
//這個(gè)例子定義了一個(gè)叫 incrementByTen 的常量退唠,該常量指向一個(gè)每次調(diào)用會(huì)加 10 的函數(shù)。調(diào)用這個(gè)函數(shù)多次得到以下結(jié)果:
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen() // 返回的值為10
incrementByTen() // 返回的值為20
incrementByTen() // 返回的值為30

如果你建立了第二個(gè) incrementer ,它將會(huì)有一個(gè)新的荤胁、獨(dú)立的 runningTotal變量的引用:

let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()
// 返回的值為  7

再次調(diào)用原來增量器 ( incrementByTen ) 繼續(xù)增加它自己的變量 runningTotal 的值瞧预,并且不會(huì)影響 incrementBySeven 捕獲的變量 runningTotal 值:

incrementByTen() // 返回的值為  40

五、逃逸閉包

  • 當(dāng)閉包作為一個(gè)實(shí)際參數(shù)傳遞給一個(gè)函數(shù)的時(shí)候仅政,我們就說這個(gè)閉包逃逸了垢油,因?yàn)樗梢栽诤瘮?shù)返回之后被調(diào)用。
  • 當(dāng)你聲明一個(gè)接受閉包作為形式參數(shù)的函數(shù)時(shí)圆丹,你可以在形式參數(shù)前寫 @escaping 來明確閉包是允許逃逸的滩愁。
    比如說:很多函數(shù)接收閉包實(shí)際參數(shù)來作為啟動(dòng)異步任務(wù)的回調(diào)。函數(shù)在啟動(dòng)任務(wù)后返回辫封,但是閉包要直到任務(wù)完成——閉包需要逃逸硝枉,以便于稍后調(diào)用。
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

函數(shù) someFunctionWithEscapingClosure(_:) 接收一個(gè)閉包作為實(shí)際參數(shù)并且添加它到聲明在函數(shù)外部的數(shù)組里倦微。如果你不標(biāo)記函數(shù)的形式參數(shù)為 @escaping 妻味,你就會(huì)遇到編譯時(shí)錯(cuò)誤。

讓閉包 @escaping 意味著你必須在閉包中顯式地引用self 欣福,比如說责球,下面的代碼中,傳給someFunctionWithEscapingClosure(_:)的閉包是一個(gè)逃逸閉包拓劝,也就是說它需要顯式地引用 self 雏逾。相反,傳給 someFunctionWithNonescapingClosure(_:) 的閉包是非逃逸閉包郑临,也就是說它可以隱式地引用self 栖博。

func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}
 
class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}
 
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"
 
completionHandlers.first?()
print(instance.x)
// Prints "100"

六、自動(dòng)閉包

  • 自動(dòng)閉包是一種自動(dòng)創(chuàng)建的用來把作為實(shí)際參數(shù)傳遞給函數(shù)的表達(dá)式打包的閉包厢洞。
  • 它不接受任何實(shí)際參數(shù)仇让,并且當(dāng)它被調(diào)用時(shí),它會(huì)返回內(nèi)部打包的表達(dá)式的值犀变。
  • 通過寫普通表達(dá)式代替顯式閉包而使你省略包圍函數(shù)形式參數(shù)的括號(hào)妹孙。
  • 自動(dòng)閉包允許你延遲處理秋柄,因此閉包內(nèi)部的代碼直到你調(diào)用它的時(shí)候才會(huì)運(yùn)行获枝。對(duì)于有副作用或者占用資源的代碼來說很有用,因?yàn)樗梢栽试S你控制代碼何時(shí)才進(jìn)行求值骇笔。

下面的代碼展示了閉包如何延遲求值省店。

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5"
 
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints "5"
 
print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"

當(dāng)你傳一個(gè)閉包作為實(shí)際參數(shù)到函數(shù)的時(shí)候嚣崭,你會(huì)得到與延遲處理相同的行為。

// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// Prints "Now serving Alex!"

上邊的函數(shù) serve(customer:) 接收一個(gè)明確的返回下一個(gè)客戶名稱的閉包懦傍。下邊的另一個(gè)版本的 serve(customer:) 執(zhí)行相同的任務(wù)但是不使用明確的閉包而是通過 @autoclosure 標(biāo)志標(biāo)記它的形式參數(shù)使用了自動(dòng)閉包”⒁ǎ現(xiàn)在你可以調(diào)用函數(shù)就像它接收了一個(gè) String 實(shí)際參數(shù)而不是閉包。實(shí)際參數(shù)自動(dòng)地轉(zhuǎn)換為閉包粗俱,因?yàn)?customerProvider 形式參數(shù)的類型被標(biāo)記為 @autoclosure 標(biāo)記说榆。

// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// Prints "Now serving Ewa!"
  • 如果你想要自動(dòng)閉包允許逃逸,就同時(shí)使用 @autoclosure@escaping 標(biāo)志寸认。
// customersInLine is ["Barry", "Daniella"]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
    customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))
 
print("Collected \(customerProviders.count) closures.")
// Prints "Collected 2 closures."
for customerProvider in customerProviders {
    print("Now serving \(customerProvider())!")
}
// Prints "Now serving Barry!"
// Prints "Now serving Daniella!"

閉包的介紹就到這里了签财。有什么不足的地方歡迎補(bǔ)充。文章大多數(shù)內(nèi)容來自:

Swift中文
YungFan老師
再次感謝偏塞!

求職廣告:本人實(shí)習(xí)生唱蒸,現(xiàn)在急需一份工作,杭州南京合肥的都可以灸叼。對(duì)我感興趣的可以私聊我 0.0神汹。謝謝~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市古今,隨后出現(xiàn)的幾起案子屁魏,更是在濱河造成了極大的恐慌,老刑警劉巖沧卢,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚁堤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡但狭,警方通過查閱死者的電腦和手機(jī)披诗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來立磁,“玉大人呈队,你說我怎么就攤上這事〕纾” “怎么了宪摧?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)颅崩。 經(jīng)常有香客問我几于,道長(zhǎng),這世上最難降的妖魔是什么沿后? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任沿彭,我火速辦了婚禮,結(jié)果婚禮上尖滚,老公的妹妹穿的比我還像新娘喉刘。我一直安慰自己瞧柔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布睦裳。 她就那樣靜靜地躺著造锅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪廉邑。 梳的紋絲不亂的頭發(fā)上哥蔚,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音蛛蒙,去河邊找鬼肺素。 笑死,一個(gè)胖子當(dāng)著我的面吹牛宇驾,可吹牛的內(nèi)容都是我干的倍靡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼课舍,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼塌西!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起筝尾,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤捡需,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后筹淫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體站辉,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年损姜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饰剥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摧阅,死狀恐怖汰蓉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情棒卷,我是刑警寧澤顾孽,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站比规,受9級(jí)特大地震影響若厚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜒什,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一测秸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦乞封、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至仔戈,卻和暖如春关串,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背监徘。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工晋修, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人凰盔。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓墓卦,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親户敬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子落剪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容