<<Swift巩固笔记>> 第7篇 闭包

228 阅读2分钟

闭包

全局函数是一个有名字, 但不会捕获任何值的闭包

嵌套函数是一个有名字, 并且可以捕获其封闭函数域内值的闭包

闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中的常量或变量值的匿名闭包

优点

* 利用上下文来推断参数和返回值类型
* 隐式返回单表达式闭包, 即单表达式闭包可以省略return关键字
* 参数名称缩写
* 尾随闭包语法

闭包表达式

var names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

排序方法

func backward(a: String, b: String) -> Bool {
    return a > b
}
var sortedNames = names.sorted(by: backward)

闭包表达式语法

格式: 函数类型 in 函数体

sortedNames = names.sorted { (a: String, b: String) -> Bool in
    return a < b
}

根据上下文推断类型

参数类型, 返回值类型都可以省略

sortedNames = names.sorted(by: { (a, b) in return a > b })

单表达式闭包的隐式返回

可以把return关键字省略

sortedNames = names.sorted(by: { (a, b) in a < b })

参数名称缩写

可以在闭包中省略参数列表

sortedNames = names.sorted(by: { $0 > $1 })

运算符方法

sortedNames = names.sorted(by: < )

尾随闭包

闭包放在函数括号后面就是尾随闭包

优点: 提高了可读性, 没有了({})的嵌套

sortedNames = names.sorted() { $0 > $1 }

当闭包是函数的唯一参数, 函数括号可以省略

map函数为数组中每一个元组调用一次闭包表达式

sortedNames = names.sorted { $0 > $1 }

let digitNames = [0:"zero", 1:"one", 2:"two", 3:"three", 4:"four", 5:"five", 6:"six", 7:"seven", 8:"eight", 9:"nine"]
let numbers = [12, 34, 56]
let strings = numbers.map {
    (value) -> String in
    var number = value
    var output = ""
    
    repeat {
        output  = digitNames[number % 10]! + output
        number /= 10
    } while number > 0
    
    return output
}
print(strings)

值捕获

闭包可以在其定义的上下文中捕获常量或变量

Swift使用捕获列表来打破这种循环强引用

func makeIncrementer(amount: Int) -> () -> Int {
    var total = 0
    func incrementer() -> Int {
        // 在这里捕获了amount和total的值
        // Swift负责被捕获变量的所有内存管理工作
        total += amount
        return total
    }
    return incrementer
}

var incrementByTen = makeIncrementer(amount: 10)
print(incrementByTen())
print(incrementByTen())
print(incrementByTen())

如果没有创建了另一个incrementer()函数, 函数内的值也会有自己独立的引用

let incrementBySeven = makeIncrementer(amount: 7)
print(incrementBySeven())

闭包是引用类型

incrementBySeven 和 incrementByTen 都是常量,

但这些常量所指向的闭包仍然可以增加其捕获的变量的值. 函数和闭包都是引用类型.

如果你将闭包赋值给我两个不同的变量或常量, 两个值都会指向同一个闭包

let anotherIncrementByTen = incrementByTen
print(anotherIncrementByTen())