swift 闭包

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

 

posted @ 2017-08-11 15:25  燃烧吧,少年  阅读(127)  评论(0编辑  收藏  举报