閉包定義
? ? ? ?閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù),可以理解成定義在一個函數(shù)內(nèi)部的函數(shù)。
? ? ? ?簡單的說它就是一個代碼塊,用{}
包起來,他可以用在其他函數(shù)的內(nèi)部,將其他函數(shù)的變量作為代碼塊的參數(shù)傳入代碼塊中,在Swift中多用于回調(diào)。這個跟Object-C中的block是一樣的。
一般形式
- 例子
//一般形式
//有參有反
let testOne: (String, String) -> String = {(str1, str2) in return str1 + str2}
print(testOne("one", "two"))
//無參有反 可以直接省略 "in"
let testTwo: () -> String = {return "test閉包"}
//無參無反
let testThree: () -> Void = {print("test閉包")}
歸納
上面的例子中:
后面是閉包的類型,而=
后面的就是一個代碼塊,也就是閉包的具體實現(xiàn),這些個OC
中的block
基本一樣。起別名
//可以用"typealias"先聲明一個閉包類型
typealias testBlock = (String) -> Void
let aaa: testBlock = {str in
print(str)
}
值捕獲
- 簡單來說就是閉包可以捕獲上下文中的常量和變量,常常是外部函數(shù)中的變量和常量
//現(xiàn)在寫一個方法,將一個閉包嵌套在函數(shù)內(nèi)部,來證明閉包可以捕獲外部函數(shù)的變量和常量,同時也能讓大家思考另一個知識.
typealias intBlock = () -> Int
func catchValue(number: Int) -> intBlock {
var totalValue = 0
let testBlock: intBlock = {
totalValue += number
return totalValue
}
return testBlock
}
let bbb = catchValue(number: 20)
print(bbb()) //20
print(bbb()) //40
print(bbb()) //60
//可以看到這里成功的捕獲到函數(shù)中的變量的值,每一次調(diào)用都會累加數(shù)值
print(catchValue(number: 20)()) //20
print(catchValue(number: 20)()) //20
print(catchValue(number: 20)()) //20
//這里的值沒有發(fā)生改變,是因為函數(shù)被調(diào)用結(jié)束就被釋放了,沒有用一個常量或變量去引用他,相當(dāng)于每次調(diào)用都是一個新的函數(shù),與OC中的匿名對象概念是相同的
由此也能看出閉包是引用類型。
逃逸閉包
概念
當(dāng)一個閉包作為參數(shù)傳入函數(shù)中,這個閉包需要等函數(shù)執(zhí)行結(jié)束返回后執(zhí)行,這種情況就稱作閉包在這個函數(shù)中逃逸。
這種情況,在涉及到異步操作時經(jīng)常用到,特別是當(dāng)網(wǎng)絡(luò)請求后要進(jìn)行請求成功后的回調(diào)時,閉包就要逃逸掉,這時就要在閉包形參錢加上@escaping
關(guān)鍵字。上例子
func showYouTest(testBlock: @escaping () -> Void) {
//做一個延遲操作
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) {
//五秒之后調(diào)用閉包
testBlock()
}
print("我是函數(shù)")
}
showYouTest {
print("我是閉包")
}