官方资料地址:https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID94
1、语法表达式
一般形式如下:
{ (parameters) -> returnType in statements }
举例如下:
let showText:(String)->Void = { (text:String)->Void in print("showContent:(text)"); } showText("hi");
根据上下文推断参数和返回值的类型,上面的代码还可以精简
let showText:(String)->Void = { text in print("showContent:(text)"); } showText("hi");
当闭包内只有一行表达式时,可以通过省略return关键字来隐式返回。
let addNum:(Int,Int)->Int = { num1,num2 in return num1+num2; } print(addNum(2,3));
如果想更加精简,可以省略参数名称直接用参数顺序$0,$1,$2调用(注意:从0开始)
let addNum:(Int,Int)->Int = { return $0+$1; } print(addNum(2,3));
尾随闭包:把闭包表达式写在函数括号之外。如果函数的最后一个参数是闭包,可以把闭包表达式写在函数外面。
func caculateTwoNum(num1:Int,num2:Int,caculFunction:(Int,Int)->Int)->Int{ return caculFunction(num1,num2); } let num = caculateTwoNum(num1: 2, num2: 3){return $0+$1}; print(num); func showHi(showFunction:()->Void){ showFunction(); } /*如果函数只有一个闭包参数,在调用该函数的时候,可以省略()*/ showHi { print("say hi"); }
可以用关键字“typealias”先声明一个闭包数据类型,类似于OC的typedef起别名
typealias AddNumBlock = (Int,Int)->Int; let addNum:AddNumBlock = {$0+$1}; let num = addNum(2,3); print(num);
2、值捕获
闭包可以在其定义的上下文中捕获常量或变量。swift中,可以捕获值的闭包的最简单形式是嵌套函数。
func captureValue(amount:Int)->()->Int{ var total = 0; let AddBlock:()->Int = { total += amount; return total; } return AddBlock; } print(captureValue(amount: 10)()); print(captureValue(amount: 10)()); print(captureValue(amount: 10)()); //输出结果为:10、10、10
上面的代码没有值捕获的原因是:没有去用一个常量或变量去引用函数,所以每次使用的函数都是新的。这个类似于OC中的匿名对象。
func captureValue(amount:Int)->()->Int{ var total = 0; let AddBlock:()->Int = { total += amount; return total; } return AddBlock; } let functionBlock = captureValue(amount: 10); print(functionBlock()); print(functionBlock()); print(functionBlock()); //输出结果为:10、20、30
3、逃逸闭包
当一个闭包作为参数传到一个函数中,需要这个闭包在函数返回之后才被执行,我们就称该闭包从函数逃逸。swift中闭包默认是非逃逸的,创建逃逸闭包需要加关键字为@escaping
func dosomething(some:@escaping ()->Void){ DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+1) { some(); } print("函数体"); } dosomething { print("逃逸闭包"); }