Swift - 闭包

2016-12-29  本文已影响14人  汪小喵

前面介绍的全局函数和嵌套函数,就是特殊的闭包。闭包是一个功能性自包含模块,可以在代码中被当作参数传递或者直接使用,类似于Objective-C中的block或其他语言中的匿名函数。
我们使用一对花括号“{}”来表示闭合并包裹着一段程序代码,由这对花括号包裹的这段代码块就是一个闭包。
(1)闭包的定义
闭包的语法形式:

{
    (参数名1:参数类型,参数名2:参数类型...) ->返回值类型  in
    闭包函数体
    return  返回值
}

in 关键字表示闭包的参数和返回值类型定义已经完成,参数和返回值将在下面的函数体中得到处理。下面是一段示例代码:

let sumFunc = {
    (x: Int, y : Int) -> Int
    in
    return x + y
}
print(sumFunc(10,20))

需要注意的是,与调用函数不同,在调用闭包时,闭包参数并不会出现外部参数名。
如果一个闭包没有参数和返回值,in都可以省略掉,那么就成了一个最简单的闭包:

let simpleFunc = {
    print("这是最简单的闭包")
}

(2)尾随闭包
尾随闭包是一个书写在函数括号之后的闭包表达式,先来看一段代码:

func calculate(opr:String, funN:(Int,Int)->Int) {
    switch opr {
    case "+":
        print("10 + 5 = \(funN(10, 5))")
    default:
        print("10 - 5 = \(funN(10, 5))")
    }
}

calculate("+", funN:{(a:Int,b:Int)->Int in return a + b})
calculate("-"){(a:Int,b:Int)->Int in return a - b}
尾随闭包

在调用函数的过程中可以看到,函数的参数很长,所以可以将小括号提前到大括号之前,这样可以增强代码的可读性。
注意:尾随闭包必须是参数列表的最后一个参数

(3)使用闭包表达式
Swift中闭包的表达式非常灵活,针对不同的情况,提供了多种闭包的简化写法:
根据上下文推断类型
我们先看一个标准的闭包:

{(a:Int, b:Int) -> Int in
    return a + b
}

Swift可以推断出参数a和b都是Int类型,,返回值也是Int类型,上面的代码可以简化成一行:

{a,b in return a + b}

下面就使用这种简化形式,编写一个示例:

func calculate(opr : String) -> (Int, Int) -> Int {
    var result : (Int, Int) -> Int
    switch opr {
    case "+":
        result = {a, b in return a + b}
    default:
        result = {a, b in return a - b}
    }
    return result
}

let f1:(Int, Int) -> Int = calculate("+")
print("10 + 5 = \(f1(10, 5))")
let f2:(Int, Int) -> Int = calculate("-")
print("10 - 5 = \(f2(10, 5))")

"result = {a, b in return a + b}"这行代码就是闭包的简化形式。

单行闭包表达式可以省略return关键字
如果在闭包内部的语句组只有一条语句,这条语句就是返回语句,此时,前面的return也可以省略。还是刚刚提到的例子,省略之后的代码如下:

func calculate(opr : String) -> (Int, Int) -> Int {
    var result : (Int, Int) -> Int
    switch opr {
    case "+":
        result = {a, b in a + b}
    default:
        result = {a, b in a - b}
    }
    return result
}

参数名称缩写
虽然根据前面所提到的,闭包已经很简洁了,但是我们还可以继续进行简化。这就用到了参数所写功能,用$0代表第一个参数,$1代表第二个参数,以此类推,$n代表第n+1个参数。我们用这种方式继续简化上面的代码:

func calculate(opr : String) -> (Int, Int) -> Int {
    var result : (Int, Int) -> Int
    switch opr {
    case "+":
        result = {$0 + $1}
    default:
        result = {$0 - $1}
    }
    return result
}

let f1:(Int, Int) -> Int = calculate("+")
print("10 + 5 = \(f1(10, 5))")
let f2:(Int, Int) -> Int = calculate("-")
print("10 - 5 = \(f2(10, 5))")

使用闭包返回值
闭包实质上是函数类型,是有返回值的,所以可以在表达式中使用闭包的返回值:

let c : Int = {
    (a : Int, b : Int) -> Int in
    return a + b
} (10,5)
print(c)

上面的代码就是给常量c赋值,等号后面是一个闭包表达式,但是由于c是Int类型,闭包表达式不能直接赋值给Int类型的c,这就需要闭包的返回值。在闭包的末尾,花括号后面跟上一对小括号,给闭包传递参数,就实现了赋值。

上一篇下一篇

猜你喜欢

热点阅读