//***********swift学习之16--闭包--***************************
/* 闭包(Closures)
* 闭包是自包含的功能代码块,可以在代码中使用或者用来作为参数传值。
* 在Swift中的闭包与C、OC中的blocks和其它编程语言(如Python)中的lambdas类似。
* 闭包可以捕获和存储上下文中定义的的任何常量和变量的引用。这就是所谓的变量和变量的自封闭,
* 因此命名为”闭包“("Closures)").Swift还会处理所有捕获的引用的内存管理。
*
* 全局函数和嵌套函数其实就是特殊的闭包。
* 闭包的形式有:
* (1)全局函数都是闭包,有名字但不能捕获任何值。
* (2)嵌套函数都是闭包,且有名字,也能捕获封闭函数内的值。
* (3)闭包表达式都是无名闭包,使用轻量级语法,可以根据上下文环境捕获值。
*
* Swift中的闭包有很多优化的地方:
* (1)根据上下文推断参数和返回值类型
* (2)从单行表达式闭包中隐式返回(也就是闭包体只有一行代码,可以省略return)
* (3)可以使用简化参数名,如$0, $1(从0开始,表示第i个参数...)
* (4)提供了尾随闭包语法(Trailing closure syntax)
*/
/*
格式 :
{
(参数:类型) ->返回类型 in
执行方法
return 返回类型
}
说明:
1;闭包主要指向函数类型
2:闭包的参数必须和函数类型的参数和返回值一致
*/
// 1.1 以下定义了一个接收参数并返回指定类型的闭包语法:
// {(parameters) -> return type in
// statements
// }
// 实例
let studname = { print("Swift 闭包实例") }
studname()
// 以下闭包形式接收两个参数并返回布尔值:
// {(Int, Int) -> Int in
// Statement1
// ---
//}
// 实例
let divide = {(val1: Int, val2: Int) -> Int in
return val1 / val2
}
let result = divide(200, 20)
print (result)
// 1.2 闭包表达式 闭包表达式是一种利用简洁语法构建内联闭包的方式。
/*
sort 函数
Swift 标准库提供了名为sort的函数,会根据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。
排序完成后,sort(_:)方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组,原数组不会被sort(_:)方法修改。
sort(_:)方法需要传入两个参数:
1.已知类型的数组
2.闭包函数:带有两个参数,这两个参数类型与数组中的元素类型相同,返回值是Bool。
*/
// 简写方法
// 1,使用sort方法和闭包进行数组排序
let numbers = [12,25,1,35,27]
let numbersSorted = numbers.sorted(by: { (n1:Int, n2: Int) -> Bool in
//进行从小到大的排序
return n1 < n2 // 根据 n1 < n2的中<的方向判断升序还是降序
})
print(numbersSorted)//[1, 12, 25, 27, 35]
// 2,闭包可以不用指定参数类型,编译器会帮我们推断的
let numbersSorted1 = numbers.sorted(by: { n1, n2 in
//进行从小到大的排序
return n2 > n1
})
print(numbersSorted1)//[1, 12, 25, 27, 35]
// 3,还可以省略参数名,直接根据数字来引用每个参数($0,$1,$2......)
let numbersSorted2 = numbers.sorted(by: {
//进行从小到大的排序
return $1 > $0
})
print(numbersSorted2)//[1, 12, 25, 27, 35]
// 4,如果闭包只包含一行代码,可以省略return关键字
let numbersSorted3 = numbers.sorted(by: {
//进行从小到大的排序
$1 > $0
})
print(numbersSorted3)//[1, 12, 25, 27, 35]
// 5,(尾随闭包)如果一个闭包是函数调用的最后一个参数,可以将它放在括号外面。提高可读性。
let numbersSorted4 = numbers.sorted() {
//进行从小到大的排序
$1 > $0
}
print(numbersSorted4)//[1, 12, 25, 27, 35]
// 6,(尾随闭包)这个换行也是可选的,所以代码可再次精简(尾随闭包)
let numbersSorted5 = numbers.sorted(){ $1 > $0 }
// 7,闭包也可以存储在变量中,像调用函数一样调用它们
let comparator = {(a: Int, b:Int) in a < b}
comparator(2,5) //true
// 8. Swift 的String类型定义了关于大于号 (>) 的字符串实现,其作为一个函数接受两个String类型的参数并返回Bool类型的值。 而这正好与sort(_:)方法的第二个参数需要的函数类型相符合。 因此,您可以简单地传递一个大于号,Swift可以自动推断出您想使用大于号的字符串函数实现:
var reversed = numbers.sorted(by: <)
print(reversed)
// 最后感谢://http://www.hangge.com/blog/cache/detail_809.html
// 1.3 一个例子
// 这是我们的model,一个例子
class imageFile {
var fileName = String()
var fileID = Int()
}
//使用
var images : [imageFile] = []
// 一般的代码形式
images.sorted(by: { (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
// 省略(->)的形式
images.sorted(by: { image1, image2 in return image1.fileID > image2.fileID })
// 带返回值的简单闭包形式
images.sorted(by: { image1, image2 in image1.fileID > image2.fileID })
// 隐含参数的形式
images.sorted(by: { $0.fileID > $1.fileID })
// 以下结果都是相同,只是书写形式不同
images = images.sorted(by: { (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
images = images.sorted(by: { image1, image2 in return image1.fileID > image2.fileID })
images = images.sorted(by: { image1, image2 in image1.fileID > image2.fileID })
images = images.sorted(by: { $0.fileID > $1.fileID })
// 1.4 尾随闭包
/*
* 尾随闭包(Trailing Closures)
* 如果函数需要一个闭包参数作为参数,且这个参数是最后一个参数,而这个闭包表达式又很长时,
* 使用尾随闭包是很有用的。尾随闭包可以放在函数参数列表外,也就是括号外。如果函数只有一个参数,
* 那么可以把括号()省略掉,后面直接跟着闭包。
*/
// Array[12,25,1,35,27]的方法map()就需要一个闭包作为参数
let numbersed = [12,25,1,35,27]
let strings = numbersed.map {
// map函数后面的()可以省略掉
// 参数列表里面 是var number 返回值 是个String 类型 in 后面跟 闭包调用后的操作
(number:Int) -> String in
// 闭包调用后的操作开始
var temNum = number
var output = ""
while temNum > 0 {
// print("temNum---\(temNum)--output--\(output)-")
output = String(temNum % 10) + output
temNum /= 10
// print("temNum---\(temNum)--output--\(output)-")
}
// 闭包调用后的操作结束
return output
}
print(strings)
// 1.5 Swift的74个常用内置函数介绍
// http://www.jb51.net/article/59777.htm
/* 1.6 捕获值
* 闭包可以根据环境上下文捕获到定义的常量和变量。闭包可以引用和修改这些捕获到的常量和变量,
* 就算在原来的范围内定义为常量或者变量已经不再存在(很牛逼)。
* 在Swift中闭包的最简单形式是嵌套函数。
*/
func increment(amount: Int) -> (() -> Int) {
var total = 0
func incrementAmount() -> Int {
total += amount // total是外部函数体内的变量,这里是可以捕获到的
return total
}
return incrementAmount // 返回的是一个嵌套函数(闭包)
}
// 闭包是引用类型,所以incrementByTen声明为常量也可以修改total
let incrementByTen = increment(amount: 10)
incrementByTen() // return 10,incrementByTen是一个闭包
// 这里是没有改变对increment的引用,所以会保存之前的值
incrementByTen() // return 20
incrementByTen() // return 30
let incrementByOne = increment(amount: 1)
incrementByOne() // return 1
incrementByOne() // return 2
incrementByTen() // return 40
incrementByOne() // return 3