闭包就是可以保存当前环境,可以传参数,可以执行的属性
格式
一般形式:{
(parameters) -> returnType in
statements
}
注意:1,参数可以是inout(输入输出参数)
2,不能设定默认值
3,如果设置可变参数必须放最后一位
4,Tuple也可以作为参数或返回值
5,in分割闭包的定义和函数体
//一般形式
let calAdd:(Int,Int)->(Int) = {
(a:Int,b:Int) -> Int in
return a + b
}
print(calAdd(100,150))
//Swift可以根据闭包上下文推断参数和返回值的类型,所以上面的例子可以简化如下
let calAdd2:(Int,Int)->(Int) = {
a,b in //也可以写成(a,b) in
return a + b
}
print(calAdd2(150,100))
//上面省略了返回箭头和参数及返回值类型,以及参数周围的括号。当然你也可以加括号,为了好看点,看的清楚点。(a,b)
//单行表达式闭包可以隐式返回,如下,省略return
let calAdd3:(Int,Int)->(Int) = {(a,b) in a + b}
print(calAdd3(50,200))
//如果闭包没有参数,可以直接省略“in”
let calAdd4:()->Int = {return 100 + 150}
print("....\(calAdd4())")
//这个写法,我随便写的。打印出“我是250”
//这个是既没有参数也没返回值,所以把return和in都省略了
let calAdd5:()->Void = {print("我是250")}
calAdd5()
•
闭包别名-typealias
typealias AddBlock = (Int, Int) -> (Int)
let Add:AddBlock = {
(c,d) in
return c + d
}
let Result = Add(100,150)
print("Result = \(Result)")
尾随闭包
当闭包作为函数的最后一个参数时,可以省略前面的括号。尾随闭包没什么特殊的作用,纯粹是一种语法上的简洁,增加易读性。
func testFunction(testBlock: ()->Void){
//这里需要传进来的闭包类型是无参数和无返回值的
testBlock()
}
//正常写法
testFunction(testBlock: {
print("正常写法")
})
//尾随闭包写法
testFunction(){
print("尾随闭包写法")
}
//也可以把括号去掉,也是尾随闭包写法。推荐写法
testFunction {
print("去掉括号的尾随闭包写法")
}
逃逸闭包
闭包作为函数的参数,但是需要函数返回值的时候才去执行这个闭包
一般用于异步函数的回调
看起来很“吊炸天”的一个名字,其实很简单。当闭包作为一个参数传递到函数时,我们知道它一般是用于函数内部的异步回调,闭包是等异步任务完成以后才调用,而函数是会很快执行完毕并返回的,所以闭包它需要逃逸,以便稍后的回调。
//例1
func doSomething(some: @escaping () -> Void){
//延时操作,注意这里的单位是秒
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
//1秒后操作
some()
}
print("函数体")
}
doSomething {
print("逃逸闭包")
}
//例2
var comletionHandle: ()->String = {"约吗?"}
func doSomething2(some: @escaping ()->String){
comletionHandle = some
}
doSomething2 {
return "叔叔,我们不约"
}
print(comletionHandle())
//将一个闭包标记为@escaping意味着你必须在闭包中显式的引用self。
//其实@escaping和self都是在提醒你,这是一个逃逸闭包,
//别误操作导致了循环引用!而非逃逸包可以隐式引用self。
//例子如下
var completionHandlers: [() -> Void] = []
//逃逸
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
//非逃逸
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}