官方资料地址: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("逃逸闭包");}