Swift讲解专题八——闭包

Swift讲解专题八——闭包

1、引言

        Swift中的闭包是有必定功能的代码块,这十分相似于Objective-C中的block语法。Swift中的闭包语法风格十分简洁,其做用和函数的做用类似。算法

2、从一个系统函数看闭包

        Swift标准函数库中提供了一个sort排序函数,对于已经元素类型的数组,调用sort函数会进行从新排序并返回新的排序后的数组。这个sort函数能够接收一个返回值为Bool类型的闭包,来肯定第一个元素是否排在第二个元素前面。代码示例以下:api

var array = [3,21,5,2,64]
func func1(param1:Int,param2:Int) -> Bool {
    return param1>param2
}
//经过传入函数的方式
//array = [64,21,5,3,2]
array = array.sort(func1)
//经过闭包的方式
//array = [2,3,5,21,64]
array = array.sort({(param:Int,param2:Int)->Bool in
                        return param<param2
                    })

Swift语言有一个很显著的特色就是简洁,能够经过上下文推断出类型的状况通常开发均可以将类型的书写省略,这也是Swift语言设计的一个思路,因为闭包是做为函数的参数传入函数中的,由于函数参数的类型是肯定,所以闭包的类型是能够被编译器推断出来的,开发者也能够将闭包的参数类型和返回值省略,上面的代码能够简写以下:数组

//将闭包的参数类型和返回值都省略
array = array.sort({(p1,p2) in return p1>p2})

实际上,若是闭包中的函数体只有一行代码,能够将return关键字也省略,这时会隐式的返回此行代码的值,以下:网络

array = array.sort({(p1,p2) in   p1>p2})

看到上面的表达式,是否是有点小震惊,闭包表达式居然能够简写成这样!然而,你仍是小看的Swift开发团队,后面的语法规则会让你明白什么是简洁的极致。能够看到上面的代码实现仍是有3部分:参数和返回值,闭包关键字,函数体。参数和返回值便是参数列表,p1,p2,虽然省略了参数类型和返回值类型,但这部分的模块还在,闭包关键字便是in,它用来表示下面将是闭包的函数体,p1>p2便是函数体,只是这里省略了return关键字。闭包中既然参数类型和返回值类型编译器均可以本身推断出来,那么参数的数量编辑器也是能够自行推断的,所以,参数列表实际上也是多余的,闭包中会自动生成一些参数名称,和实际的参数数量向对应,例如上面sort函数中的闭包有两个参数,系统会自动生成$0和$1这两个参数名,开发者能够直接使用,由于参数列表都会省略了,那么也再也不须要闭包关键字in来分隔参数列表与函数体,这时,闭包的写法实际上变成了以下的模样:闭包

array = array.sort({$0<$1})

你没有看错,加上左右的大括号,一共7个字符,完成了一个排序算法。除了Swift,我不知道是否还有第二种语言能够作到。抛开闭包不说,Swift中还有一种语法,其能够定义类型的运算符方法,例如String类型能够经过=,<,>来进行比较,其实是String类中实现了这些运算符方法,在某种意义上说,一个运算符即相似与一个函数,那么好了,sort函数中须要传入的方法对于某些类型来讲实际上只是须要一个运算符,示例以下:app

array = array.sort(>)

此次你能够真的震惊了,完成排序新算法只须要一个字符,彻彻底底的一个字符。异步

3、Swift中闭包的更多特色

        Swift中的闭包还有一个有趣的特色,首先闭包是做为参数传入另外一个函数中的,所以常规的写法是将闭包的大括号写在函数的参数列表小括号中,若是闭包中的代码不少,这时在代码结构上来看会变得并不太清晰,为了解决这个问题,Swift中这样规定:若是这个闭包参数是函数的最后一个参数,开发者能够将其拉出小括号,在函数尾部实现闭包代码,示例以下:编辑器

//闭包结尾
func func2(param1:Int,param2:()->Void)->Void{
    param2()
    print("调用了func2函数")
}
func2(0){
        print("闭包中的内容")
}

若是一个函数中只有一个参数,且这个参数是一个闭包,那么开发者使用闭包结尾这种写法,彻底能够将函数的参数列表小括号也省略掉,示例以下:函数

func func3(param:()->Void)->Void{
    param()
    print("调用了func3函数")
}
func3{
    print("闭包中的内容")
}

Swift中还有一个闭包逃逸的概念,这个很好理解,当闭包做为参数传递进函数时,若是这个闭包只在函数中被使用,则开发者能够将这个闭包声明成非逃逸的,即告诉系统当此函数结束后,这个闭包的声明周期也将结束,这样作的好处是能够提升代码性能,将闭包声明称非逃逸的类型使用@noescape关键字,示例以下:性能

func func3(@noescape param:()->Void)->Void{
    param()
    print("调用了func3函数")
}
func3{
    print("闭包中的内容")
}

逃逸的闭包经常使用于异步的操做,例如这个闭包是异步处理一个网络请求,只有当请求结束后,闭包的声明周期才结束。非逃逸的闭包还有一个有趣的特色,在其内部若是须要使用self这个关键字,self能够被省略。

        闭包也能够被自动的生成,这种闭包被称为自动闭包,自动闭包能够自动将表达式封装成闭包,开发者不须要再写闭包的大括号格式,自动闭包不接收参数,返回值为其中表达式的值。示例以下:

//自动闭包演示
var list = [1,2,3,4,5,6]
//建立一个显式闭包
let closures = {
    list.removeFirst()
    list.append(7)
}
//将打印[1,2,3,4,5,6]
print(list)
//执行闭包
closures()
//将打印[2,3,4,5,6,7]
print(list)
func func4(closure:()->Void) -> Void {
    //执行显式的闭包
    closures()
}
func func5(@autoclosure auto:()->Void) -> Void {
    //执行自动闭包
    auto()
}
//显式闭包 须要大括号
func4(closures)
//将打印[3,4,5,6,7,7]
print(list)
//将表达式自动生成闭包
func5(list.append(8))
//将打印[3,4,5,6,7,7,8]
print(list)

自动闭包默认是非逃逸的,若是要使用逃逸的闭包,须要手动声明,以下:

func func5(@autoclosure(escaping) auto:()->Void) -> Void {
    //执行自动闭包
    auto()
}

专一技术,热爱生活,交流技术,也作朋友。

——珲少 QQ群:203317592

相关文章
相关标签/搜索