Swift--闭包

  • 闭包的概念

  • Swift闭包表达式

  • 使用闭包返回值

  • 使用尾随闭包

  • 捕获上下文中的变量和常量

支持闭包有两个前提
1、支持函数类型,能够将函数作为参数或返回值传递。
2、支持函数嵌套。

概念

闭包:是自包含的匿名函数代码块,可以作为表达式、函数参数和函数返回值,闭包表达式的运算结果是一种函数类型。

Swift中的闭包类似于Objective-C中的代码块、C++和C#中的Lambda表达式、Java中的匿名内部类。

Swift闭包表达式-标准写法

{(参数列表) - > 返回值类型 in
语句组
}

标准形式的闭包

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

//标准写法
func calculate2(opr: String)-> (Int, Int)->Int {
    var result:(Int, Int) -> Int

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

let f3: (Int, Int) -> Int = calculate2(opr: "+")
print("10 + 5 = \(f3(10, 5))" )

let f4: (Int, Int) -> Int = calculate2(opr: "-")
print("10 - 5 = \(f3(10, 5))")
Swift闭包表达式--类型推断简化

类型推断简化的闭包

{(a, b) in return a + b }
{a, b in return a + b } //参数列表括号也可以省略

//类型推断简化
func calculate3(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 f5 = calculate3(opr: "+")
print("10 + 5 = \(f5(10, 5))" )

let f6: (Int, Int) -> Int = calculate3(opr: "-")
print("10 - 5 = \(f6(10, 5))")
Swift闭包表达式--隐藏return关键字

如果在闭包内部语句组只有一条语句, 如return a + b等,那么这种语句都是返回语句。前面的关键字return 可以省略,省略形式如下:
{a, b in a + b}

//隐藏return关键字

func calculate4(opr: String)-> (Int, Int)->Int {
    var result:(Int, Int) -> Int

    switch (opr) {
    case "+":
        result = {
            (a, b) in
            let c = a + b
            print(c)
            return c
        }
    default:
        result = { a, b in a - b } //也可以写成一行
    }
    return result
}

let f7 = calculate4(opr: "+")
print("10 + 5 = \(f7(10, 5))" )

let f8: (Int, Int) -> Int = calculate4(opr: "-")
print("10 - 5 = \(f8(10, 5))")
Swift闭包表达式--省略参数名
屏幕快照 2019-10-02 下午10.26.29.png

//省略参数名

func calculate5(opr: String)-> (Int, Int)->Int {
    var result:(Int, Int) -> Int

    switch (opr) {
    case "+":
        result = {
            let c = $0 + $1
            print(c)
            return c
        
        }
    default:
        result = { $0 - $1 } // $0 == a  $1 == b
    }
    return result
}

let f9 = calculate5(opr: "+")
print("10 + 5 = \(f9(10, 5))" )

let f10: (Int, Int) -> Int = calculate5(opr: "-")
print("10 - 5 = \(f9(10, 5))")

使用闭包返回值

闭包表达式本质上是函数类型,是有返回值的,我们可以直接在表达式中使用闭包的返回值。重新修改add和sub闭包,示例代码如下:

//使用闭包返回值

let c1: Int = {(a: Int, b: Int) ->Int in
    return a + b
}(120, 10)

print("120 + 10 = \(c1)")

let c2: Int = {(a: Int, b: Int)-> Int in
    return a - b
}(120, 10)

print("120 - 10 = \(c2)")

:理解闭包返回值,可以将闭包看成一个函数。如图所示把灰色部分替换为函数,那么函数调用时后面是小括号的参数列表。

image.png

使用尾随闭包

闭包表达式可以作为函数的参数传递,如果闭包表达式很长,就会影响程序的可读性。尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。

//使用尾随闭包
func calculate6(opr: String, funN: (Int, Int)-> Int) {
    switch (opr) {
    case "+":
        print("10 + 5 = \(funN(10, 5))")
    default:
        print("10 - 5 = \(funN(10, 5))")
    }
}

calculate6(opr: "+", funN: {
    (a: Int, b: Int)-> Int in return a + b
})

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

calculate6(opr: "+") {
    $0 + $1
}

calculate6(opr: "-", funN: {
    (a: Int, b: Int)-> Int in return a - b
})

calculate6 (opr: "-") {
     (a: Int, b: Int)-> Int in return a - b
}

calculate6(opr: "-") {
    $0 - $1
}

注意:有一些窍门可以帮助我们判断是闭包还是函数,闭包中往往有一些关键字,例如in, 还有缩写参数$0, $1...等,这些特征在函数中是没有的。

捕获上下文中的常量和变量

嵌套函数或闭包可以访问它所在上下文的变量和常量,这个过程称为捕获值(capturing value)。即便是定义这些常量和变量的原始作用域已经不存在,嵌套函数或闭包仍然可以在函数体内或闭包体内引用和修饰这些值。

用嵌套函数来捕获上下文中的变量和常量
//用嵌套函数来捕获上下文中的变量和常量

func makeArray()-> (String)->[String] {

    var ary:[String] = [String]()

    func addElement(element: String)->[String] {
        ary.append(element)
        return ary
    }
    return addElement
}

let f11 = makeArray()
print("---f11---")
print(f11("张三"))
print(f11("李四"))
print(f11("王五"))

let f12 = makeArray()
print("---f12---")
print(f12("刘备"))
print(f12("张飞"))
print(f12("关羽"))

嵌套函数对ary进行值的捕获之后,就会把上一次的值接着使用,这样的话ary里面的内容会被增加。

输出结果如下图:


image.png

//无嵌套函数时
func makeArray2(element:String)-> [String] {

    var ary:[String] = [String]()
    ary.append(element)
    return ary
}

let f13 = makeArray2(element: "张三")
print(f13)

let f14 = makeArray2(element: "李四")
print(f14)

let f15 = makeArray2(element: "王武")
print(f15)

无嵌套函数时,每次调用函数时ary都被重新初始化一次
输出结果如图:


image.png
用闭包来捕获上下文中的变量和常量
//用闭包来捕获上下文中的变量和常量

func makeArray3()-> (String)->[String] {

    var ary:[String] = [String]()

//    func addElement(element: String)->[String] {
//        ary.append(element)
//        return ary
//    }
//    return addElement

    return {
        (element: String) -> [String] in
        ary.append(element)
        return ary
    }
}

let f16 = makeArray3()
print("---f16---")
print(f16("贾宝玉"))
print(f16("林黛玉"))
print(f16("薛宝钗"))

let f17 = makeArray3()
print("---f17---")
print(f17("曹操"))
print(f17("曹丕"))
print(f17("曹植"))

输出结果如下图:


image.png

你可能感兴趣的:(Swift--闭包)