在前面, 我们把函数的一些基本用法还有一些注意事项都讲完了, 这次我们来讲讲其他的东西:
1.闭包的简介
看到这里, 或许有人想着, 又是一个新的东西, 其实不以为然, 所谓的闭包其实就是OC中block, 只是在block的基础上做出了稍微的改变, 但最终的原理和block八九不离十, 闭包除去可以使用类似block的原理之外, 还多了一些特性, 比如闭包可以捕获和存储其所在上下文中任意常量和变量的引用。 这就是所谓的闭合并包裹着 这些常量和变量,俗称闭包.
其实闭包我们在函数的章节中也讲过, 全局和嵌套函数实际上是特殊的闭包, 而闭包是有三种不同的形态:
1. 全局函数是一个有名字但不会捕获任何值的闭包
2. 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
3. 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的没有名字的闭包
PS: 关于捕获这个概念, 后面会去慢慢讲解
2.闭包的表达式
嵌套函数是一种在较复杂函数中方便进行命名和定义自包含代码模块的方式, 当然, 有时候撰写小巧的没有完整定义和命名的类函数结构也是很有用处的, 尤其是在处理一些函数并需要将另外一些函数作为该函数的参数时.
闭包表达式是一种利用简洁语法构建内联闭包的方式. 闭包表达式提供了一些语法优化, 使得撰写闭包变得简单明了.
3.Sorted函数
Swift 标准库提供了sorted函数, 会根据您提供的排序闭包将已知类型数组中的值进行排序, 一旦排序完成, 函数会返回一个与原数组大小相同的新数组, 该数组中包含已经正确排序的同类型元素, 比如:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = sorted(names, backwards)
println(reversed)
// 打印出来的结果: [Ewa, Daniella, Chris, Barry, Alex]
PS: 其实我们是可以理解成为一个数组提供了排序的方法, 根据backwards函数里的两个形参判断, 是否返回true, 如果是的话, s1就放在s2之前, 依此类推, 所以打印出来的结果就和上面的例子一样.
4.闭包的表达式语法
闭包表达式语法可以使用常量, 变量和 inout 类型作为参数,但不提供默认值。 也可以在参数列表的最后使用可变参数, 元组也可以作为参数和返回值, 比如:
reversed = sorted(names, {(s1: String, s2: String) -> Bool in return s1 > s2 })
let name = ["a", "b", "c", "d", "e", "f", "g"]
var a = reverse(name)
println(a)
// 打印出来的结果: [g, f, e, d, c, b, a]
PS: 需要注意的是内联闭包参数和返回值类型声明与 backwards 函数类型声明相同, 在这两种方式中,都写成了 (s1: String, s2: String) -> Bool 类型, 然而在内联闭包表达式中, 函 数和返回值类型都写在大括号内,而不是大括号外, 闭包的函数体部分由关键字 in 引入, 该关键字表示闭包的参数和返回值类型定义已经完成, 闭包函数体即将开始.
5.根据上下文推断类型
因为排序闭包是作为函数的参数进行传入的,Swift 可以推断其参数和返回值的类型, 比如:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
reversed = sorted(names, { s1, s2 in return s1 > s2 } )
println(reversed)
// 打印出来的结果: [Ewa, Daniella, Chris, Barry, Alex]
在单行闭包的时候, 我们可以不加return, 比如:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
reversed = sorted(names, { s1, s2 in s1 < s2 } )
println(reversed)
// 打印出来的结果: [Alex, Barry, Chris, Daniella, Ewa]
PS: 实际上任何情况下, 通过内联闭包表达式构造的闭包作为参数传递给函数时, 都可以推断出闭包的参数和返回值类型, 这意味着您几乎不需要利用完整格式构造任何内联闭包,而且在单行闭包时, 我们还可以省略return这个关键字.
6.参数的简写
在闭包当中, 其实参数我们还有另外一种写法, 而且是非常的简单, 那就是用( $0, 1, 2)来代替, 比如:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = sorted(names, {$0 < $1})
println(reversed)
// 打印出来的结果: [Alex, Barry, Chris, Daniella, Ewa]
PS: 这里面的($0, 1), 其实对应的就是闭包中的 s1 还有 s2.
7.运算函数
其实刚刚的那个例子并不是最简化的, 最简化的例子在这里, 让我们一起来看看吧:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = sorted(names, <)
println(reversed)
// 打印出来的结果: [Alex, Barry, Chris, Daniella, Ewa]
这里就不用多做解释了吧, 直接一眼明了, 想怎么样排序就怎么样排序.
好了, 这次就讲到这里了, 下次我们继续~