Swift特有语法:闭包

1. 闭包定义

闭包:闭包是自包含的函数代码块,可以在代码中被传递和使用。闭包可以捕获和存储其所在上下文中任意常量和变量的引用。 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。Swift 会管理在捕获过程中涉及到的所有内存操作。

闭包采取如下三种形式:

  • 全局函数是一个有名字但不会捕获任何值的闭包
  • 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
  • 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的匿名闭包

2. sort函数

sorted 函数(The Sorted Function):Swift 标准库提供了sorted函数,会根据您提供的基于输出类型排序的闭包函数将已知类型数组中的值进行排序。 一旦排序完成,函数会返回一个与原数组大小相同的新数组,该数组中包含已经正确排序的同类型元素。

sorted函数需要传入一个参数:

  • 闭包函数,该闭包函数需要传入与数组类型相同的两个值,并返回一个布尔类型值来告诉sorted函数当排序结束后传入的第一个参数排在第二个参数前面还是后面。如果第一个参数值出现在第二个参数值前面,排序闭包函数需要返回true,反之返回false

我们通过sorted函数,使用闭包进行排序,代码如下:

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
        func backwards(s1 : String, s2 : String)->Bool{
            return  s1>s2
        }
        let reversed = names.sort(backwards)
        for item in reversed{
            print("item = : \(item)")
        }

3. 闭包表达式语法(Closure Expression Syntax)

闭包表达式语法有如下一般形式:

{ (parameters) -> returnType in
    statements
}

优化了backwards函数对应的闭包表达式版本的代码:

let reversed = names.sort({(s1 : String , s2 : String) -> Bool in return s1 > s2})

根据上下文推断类型(Inferring Type From Context):实际上任何情况下,通过内联闭包表达式构造的闭包作为参数传递给函数时,都可以推断出闭包的参数和返回值类型,优化后代码如下:

let reversed = names.sort({s1 , s2 in return s1 > s2})

参数名称缩写(Shorthand Argument Names):Swift 自动为内联函数提供了参数名称缩写功能,您可以直接通过$0,$1,$2来顺序调用闭包的参数。优化后代码如下:

let reversed = names.sort({ $0 > $1 })

4. 尾随闭包

尾随闭包(Trailing Closures):如果需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。 尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。

下例介绍了如何在map方法中使用尾随闭包将Int类型数组[16,58,510]转换为包含对应String类型的数组["OneSix", "FiveEight", "FiveOneZero"],代码如下:

let digitNames = [0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",
            5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"]
        let numbers = [16, 58, 510]
        let strings = numbers.map{
            (var number) -> String in
            var output = ""
            while number > 0 {
                output = digitNames[number % 10 ]! + output
                number /= 10
            }
            return output
        }
        
        for item in strings {
            print("item = \(item)")
        }

4.1 Swift中map

Map函数会遍历集合类型并对其中的每一个元素进行同一种的操作。Map的返回值是一个所得结果的数组。例如:我们要对一个数组里面的数据进行平方操作,常见的代码如下:

let values: [Double]= [2.0,4.0,6.0,8.0]
var squares: [Double] = []
for value in values {
    squares.append(value * value)
}

上面的代码中,我们使用了常规的for in遍历操作对其中的元素进行了平方操作,然后将计算的结果追加到一个变量数组里面。虽然该部分的代码很好的完成了要求,但是在Swift中我们还有更简洁和安全的代码(上面的squaers是一个变量可能出现无意的数据修改)。下面来看看使用Map进行操作的代码:

let values: [Double]= [2.0,4.0,6.0,8.0]
let squares: [Double] = values.map{$0 * $0}
//该段代码不仅更加简洁而且squares是一个不可变的常量。

5. 捕获值

捕获值(Capturing Values):闭包可以在其定义的上下文中捕获常量或变量。 即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。代码如下:

func makeIncrementor(forIncrement amount : Int) -> () -> Int{
            var runningTotal = 0
            func incrementor() -> Int{
                runningTotal += amount
                return runningTotal
            }
            return incrementor
        }
        let incrementByTen = makeIncrementor( forIncrement: 10)
        let number = incrementByTen()
        print("incrementByTen = \(number)")

makeIncrementor返回类型为() -> Int。 这意味着其返回的是一个函数,而不是一个简单类型值。 该函数在每次调用时不接受参数只返回一个Int类型的值。 

 

posted @ 2016-06-13 10:13  自相矛盾  阅读(249)  评论(0编辑  收藏  举报