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

 

 

 

 

posted @ 2017-03-23 15:58  Frank9098  阅读(98)  评论(0)    收藏  举报