介紹: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老師
一嘲碱、閉包的介紹
- 閉包的含義
閉包是匿名函數(shù)
閉包是可以被傳遞和引用的一個(gè)獨(dú)立模塊
閉包能夠捕獲和存儲(chǔ)定義在其上下文中的任何常量和變量的引用金砍,這也就是所謂的閉合并包裹那些常量和變量,因此被稱為“閉包”
閉包和函數(shù)一樣都是引用類型
-
實(shí)際上
函數(shù)
和內(nèi)聯(lián)函數(shù)
都是特殊的閉包麦锯。- 全局函數(shù)是一個(gè)有名字但不會(huì)捕獲任何值的閉包恕稠;
- 內(nèi)嵌函數(shù)是一個(gè)有名字且能從其上層函數(shù)捕獲值的閉包;
- 閉包表達(dá)式是一個(gè)輕量級(jí)語法所寫的可以捕獲其上下文中常量或變量值的沒有名字的閉包离咐。
- 閉包的書寫
// 基本書寫方式
{ (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ù)不能提供默認(rèn)值,其他和函數(shù)一樣宵蛀,閉包表達(dá)式語法
二接谨、閉包主要知識(shí)點(diǎn)
- 參數(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ù)名,你也可以通過 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ù)runningTotal
和amount
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)容來自:
求職廣告:本人實(shí)習(xí)生唱蒸,現(xiàn)在急需一份工作,杭州南京合肥的都可以灸叼。對(duì)我感興趣的可以私聊我 0.0神汹。謝謝~~~