007-Swift3.0之闭包
一、闭包的语法
{ (parameters) -> returnType in
}
闭包表达式的参数可以是inout参数,但不能设置默认值
闭包表达式的参数可以是可变参数(参数个数可变),但是必须放在最后一位
var arr1: [Int] = [20, 21, 12, 2, 5, 9, 3] arr1.sorted(by: { (a: Int, b: Int) -> Bool in return a < b })
闭包的语法格式:
1)闭包使用大括号{}括起
2)由于闭包是内部调用,所以可忽略外部参数名,只需内部参数名即可
3)闭包使用关键字in
二、最典型的闭包:sort和sorted
1.sort方法
无返回值,改变的是调用对象的值,所以调用对象必须是var类型
var arr1: [Int] = [10, 30, 12, 33, 21, 20] arr1.sort() // arr1 = [10, 12, 20, 21, 30, 33] arr1.sort { (a, b) -> Bool in return a > b } // arr1 = [33, 30, 21, 20, 12, 10]
2.sorted方法
生成一个新的数组,调用对象的值不发生改变,所以调用对象可以是let类型
let arr2: [Int] = [10, 30, 12, 33, 21, 20] let arr = arr2.sorted() // arr = [10, 12, 20, 21, 30, 33] print(arr2) // arr2 = [10, 30, 12, 33, 21, 20]
3.排序闭包函数是作为参数传入的,Swift是可以推断出类型的,所以可省略
var arr3: [Int] = [10, 30, 12, 33, 21, 20] arr3.sort { a, b in return a > b } // arr3 = [33, 30, 21, 20, 12, 10] let array = arr3.sorted { a, b in return a > b } // array = [33, 30, 21, 20, 12, 10]
4.闭包中只有一行代码,所以可省略return
var arr4: [Int] = [10, 30, 12, 33, 21, 20] arr4.sort { a, b in a > b } let aaa = arr4.sorted { a, b in a > b } // aaa = [33, 30, 21, 20, 12, 10]
5.参数名称缩写
var arr5: [Int] = [10, 30, 12, 33, 21, 20] arr5.sort(by: {$0 > $1}) // arr5 = [33, 30, 21, 20, 12, 10] let bbb = arr5.sorted(by: {$0 > $1}) // bbb = [33, 30, 21, 20, 12, 10]
6.运算符方法
var arr6: [Int] = [10, 30, 12, 33, 21, 20] arr6.sort(by: >) // arr6 = [33, 30, 21, 20, 12, 10] let ccc = arr6.sorted(by: >) // ccc = [33, 30, 21, 20, 12, 10]
7.闭包的简化
var arr2: [Int] = [20, 21, 12, 2, 5, 9, 3] arr2.sorted(by: { (a: Int, b: Int) -> Bool in return a > b }) arr2.sorted(by: { a, b in return a > b }) arr2.sorted(by: { a, b in a > b }) arr2.sorted(by: { $0 > $1 }) arr2.sorted(by: >) // 另外一种形式调用闭包--代码更有可读性 arr2.sorted(){ a, b in return a > b } // 由于小括号()里面没有其他的参数,已经空啦,所以也可以省略 arr2.sorted { a, b in return a > b }
三、尾随闭包
如果你需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性
尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用
在使用尾随闭包时,你不用写出它的参数标签
func someFunction(closure: () -> Void) { // 函数体部分 } // 1)使用普通闭包调用 someFunction(closure: { // 闭包主体部分 }) // 2)使用尾随闭包调用 someFunction() { // 闭包主体部分 } // 3)如果只有闭包这一个参数,那么还可以这么简写 someFunction { // 闭包主体部分 }
示例:将numbers数组中的数字分别转化为英文字符串
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 string = numbers.map { (number) -> String in var number = number var output = "" repeat { output = digitNames[number % 10]! + output number /= 10 } while number > 0 return output } string // ["OneSix", "FiveEight", "FiveOneZero"]
四、值捕获
1.简单实例
var arr3 = [30, 21, 23, 40, 54] var num = 40 arr3.sorted{ a, b in abs(a - num) < abs(b - num) }
2.实例
// () -> Int:返回的是一个函数 // forIncrement:外部参数名 // amount:内部参数名 // amount:incrementer每次被调用时runningTotal将要增加的量 // makeIncrementer:函数还定义了一个嵌套函数incrementer,用来执行实际的操作 // incrementer函数简单地使runningTotal增加amount,并将其返回 func makeIncrementer(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 // 单独地看incrementer函数,没有任何参数,但是在函数体内访问了runningTotal和amount变量 // 这是因为它从外围函数中捕获了runningTotal和amount变量的引用 func incrementer() -> Int { runningTotal += amount return runningTotal } return incrementer } let aa = makeIncrementer(forIncrement: 10) // 这里调用函数makeIncrementer,返回一个闭包incrementer,并且还有在闭包外围定义了一个初始值runningTotal = 0、amount = 10 aa() // 调用闭包 runningTotal = 0 + 10 = 10 aa() // 调用闭包 runningTotal = 10 + 10 = 20 aa() // 调用闭包 runningTotal = 20 + 10 = 30 let bb = makeIncrementer(forIncrement: 3) // 这里重新调用函数makeIncrementer,返回一个闭包incrementer,并且还有在闭包外围定义了一个初始值runningTotal = 0、amount = 3 bb() // 调用闭包 runningTotal = 0 + 3 = 3 bb() // 调用闭包 runningTotal = 3 + 3 = 6 bb() // 调用闭包 runningTotal = 6 + 3 = 9 // 再次调用原来的aa会继续增加它自己的runningTotal,该变量和bb中捕获的变量没有任何联系 aa() // 调用闭包 runningTotal = 30 + 10 = 40

浙公网安备 33010602011771号