每次看闭包的时候,都觉得挺简单的。不就是Objective-C中的block嘛,但是长时间不看,再来用的时候有些地方老是印象模糊,特别是一些省略写法。好记性不如烂笔头,还是决定整理整理记下来。
闭包描述排序方法
swift中有个排序的方法,它会根据你提供的闭包,对数组已知类型的元素进行排序。原数组:
因为这个数组的元素类型是字符串,所以需要传的闭包类型是写个这样类型的函数,并编译,就得出了排序之后的新数组了。
闭包语法
闭包的一般格式:
上面的例子可以闭包的形式替代:
闭包的内容是以开始的,标志着闭包的参数和返参已经定义完成,准备开始功能实现了。因为这个闭包的内容很少,所以甚至可以写成一行。
类型推断
因为闭包是作为一个参数传入一个方法,所以swift可以推断它参数的类型。上面的例子中,对一个元素为字符串的数组排序,所以传入的闭包类型必须为,这就意味着和类型不用写。因为所有的类型都可以推断,所以箭头和圆括号也可以删掉。当然如果继续写类型的话,在swift中是鼓励的,这样可以方便代码的读者阅读。
单行表达式的含蓄返回
如果闭包只有一句表达式,那么它会自动加上返回的功能,所以可以省略。
速写参数名
swift会自动对内联闭包提供速写参数名,比如、、等等。如果用这种方式的话,参数列表和也可以删掉。
算子
上面这个例子甚至还有一种更简单的方式,就是在闭包中直接传入一个大于的算子,swift可以推断你想要它针对字符串特定的实现。
尾随闭包
如果闭包是作为一个函数的最后一个参数传入,并且这个闭包很长,那么可以使用尾随闭包替代。尾随闭包是写在函数的调用括号外面,虽然它还是函数的一个参数。上面的例子就可以使用尾随闭包。
使用前:
使用后:
如果闭包是这个函数或方法的唯一参数,而且又是一个尾随闭包的话,那么连括号都可以删掉。
复杂一点的例子。用把一个类型的数组转化成类型的数组。
方法:
在这个闭包里,不用明确每个参数的类型是,因为闭包会自动推断。
捕捉变量
闭包可以捕获周围上下文中的常量和变量。现在有一个嵌套闭包。函数包含一个嵌套函数。嵌套函数捕获两个变量,和。通过捕获两个变量之后,每次调用函数,嵌套函数都会让加,并以闭包的形式作为函数的返参返回。
定义一个变量接收函数返回的闭包,并连续调用。
在函数里定义了一个变量用来储存累计增加的总数,初始化为0。调用返回来一个类型的闭包。第一次调时,为0,为10,调用后,返回10(0+10),同时变为10,以此类推。如果再调用一次函数生成一个新的闭包,并调用该闭包的话,那么该闭包捕获的的初始值仍然为0,这时候再重新调用,它的仍然为30,不受新生成的闭包的影响。
闭包是指针类型
定义一个常量指向闭包时,只是定义一个指向闭包的常量指针,而不是闭包本身是常量。比如上例中,如果定义另一个常量指向,它其实指向的是同一个闭包。
逃逸闭包
当一个闭包作为一个参数传入一个函数,并且这个闭包是在这个参数执行返回之后调用,那么这个闭包就是一个逃逸闭包,需要在参数类型前面用字段修饰,标明这个闭包可以逃逸,否则会报编译错误。
使用标记闭包,意味着你在闭包内部必须明确指向。
自动闭包
自动闭包用修饰,使用自动闭包可以延缓及时性要求不那么高的闭包的编译。但是使用自动闭包会增加代码的阅读难度。
Overusing autoclosures can make your code hard to understand. The context and function name should make it clear that evaluation is being deferred.
备注
Xcode版本:9.3.1
Swift版本:4.1
官方文档:Closures
领取专属 10元无门槛券
私享最新 技术干货