1、Swift入门学习笔记(第一版),对Swift的基础知识点进行梳理总结。知识点一直在变,只是作为参考,以苹果官方文档为准~
2、在学习完基本的知识点以后会结合官方文档及相关资料,在此版本的基础上进行添加更改。
八、闭包
1、闭包表达式
{ (parameters) -> returnType in
statements
}
//以一个逆序排列的例子来展开对闭包知识点的讲解
let names = ["Chris","Alex","Ewa","Barry","Daniella"]
1.1、不使用闭包
func backwards(s1:String,s2:String) -> Bool {
return s1 > s2
}
var reversed = names.sort(backwards)
print(reversed)
Output:
["Ewa","Daniella","Chris","Alex"]
补充:
sort函数
a、sort函数是Swift的标准库函数,根据提供的用于排序的闭包函数将一直类型数组中的值进行排序排序完成,返回一个与原数组等大小,包含同类型元素且正确排序的新数组。原数组不会被改变
b、传入参数
已知类型数组、
闭包函数:该闭包函数传入与数组同类型的两个值,并返回Bool类型值表示排序结束后传入的第一个参数在第二个参数的前面还是后面,前面返回true,后面返回false
1.2、使用闭包
reversed = names.sort({ (s1:String,s2:String) -> Bool in return s1 < s2 }) print(reversed)
Output:
["Alex","Ewa"]
a、闭包表达式可以使用常量、变量、inout、可变作为参数,不提供默认值。元组也可作参数和返回值
b、in关键字引入函数体
1.3、根据上下文推断类型
reversed = names.sort({s1,s2 in return s1>s2})
print(reversed)
由于sort函数期望的第二个参数类型是(String,String) -> Bool
,因此所有类型都可省略可以被正确推断
Output:
["Ewa","Alex"]
实际在任何情况下,通过内联闭包表达式构造的闭包作为参数传递给函数时,都可以推断出闭包的参数和返回值类型,因此几乎不需要利用完整格式构造任何内联闭包
当然完整格式的闭包代码可读性较高
1.4、单表达式闭包隐式返回
reversed = names.sort({s1,s2 in s1 < s2})
print(reversed)
in 引入的函数主体只有一个语句时刻省略return
Output:
["Alex","Ewa"]
1.5、参数名称缩写
Swift自动为内联函数提供此功能,可直接通过$0,$1,$2
来顺序调用闭包的参数
reversed = names.sort({$0 > $1})
print(reversed)
Output:
["Ewa","Alex"]
1.6、运算符函数
reversed = names.sort(<)
print(reversed)
Swift的String类型已定义关于<、=、>
等的字符串实现,会自动转化为与前面相同的闭包函数,其参数和返回值类型又正好与sort的第二个参数要求类型相符,因此仅传递一个运算符即可
Output:
["Alex","Ewa"]
2、尾随闭包
当闭包表达式太长时,将闭包作为最后一个参数,利用尾随闭包增强函数的可读性
reversed = names.sort(){$0 > $1}
print(reversed)
此处的sort函数只有闭包表达式一个参数,()也是可以省略的
Output:
["Ewa","Alex"]
3、捕获值
闭包可在其定义的上下文捕获常量或变量,即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数中引用和修改这些值
//以Swift中最简单的闭包形式嵌套函数为例,
func rollingNumber(forIncrement amount:Int) -> ()->Int {
var total = 0
func incrementor() -> Int {
total += amount
return total
}
return incrementor
}
incrementor() -> Int
中没有任何参数,但是函数体内访问了total
和amount
变量,这是通过其捕获在包含它的函数体内已存在的total
和amount
变量的引用而实现。
捕获变量引用,保证变量在调用完rollingNumber
函数不会消失,下一次执行incrementor
函数时,total
仍可以继续增加
let incrementByTen = rollingNumber(forIncrement: 10)
print(incrementByTen()) print(incrementByTen()) print(incrementByTen()) let incrementByEight = rollingNumber(forIncrement: 8) print(incrementByEight())
Output:
10 20 30 8
从结果可以知道incrementByEight
捕获的变量与incrementByTen
没有任何关系,互不干涉
print(incrementByTen())
Output:
40
仍在原来30的基础上增加
4、闭包是引用类型
可以赋值,指向同一个闭包
let alsoTen = incrementByTen
print(incrementByTen())
Output:
50