第七章 闭包
c++没有闭包,swift有闭包。c++有些类似的概念是Lambda函数,但是闭包概念更丰富,更完善,更灵活。
闭包表达式语法:
{ (parameters) -> returnType in
statements
} //闭包参数不能设置默认值,可以是inout参数,也可以是可变参数。
闭包根据上下文可以推断类型,可以省略参数和返回值类型,单行表达式闭包还可以省略return关键字,对于内联闭包还可以省略参数名称,直接用$0,$1,$2来表示参数。但是个人认为,为了代码可读性,上面的方便还是不要省略了。
尾随闭包
func someFunctionThatTakesAClosure(closure: () -> Void) {
//函数体部分
} //函数是以函数类型作为参数,闭包表达式是作为最后一个参数传递给函数
//这时可以采用尾随闭包
//以下不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
//闭包主体部分
})
//以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
//闭包主体部分
}
swift中函数和闭包是引用类型,c++中函数是指针,swift没有指针,只有值类型和引用类型。swift的所有基本类型Int、Double、Float、Bool、String、Array、Dictionary都是值类型,结构体和枚举也是值类型,但类是引用类型,这点和c++不同。将一个类实例赋值给两个变量,其实是对这个实例的两次引用,任何修改都会改变另外一个变量的值。
逃逸闭包
当一个闭包作为参数传递到一个函数,但是这个闭包在函数返回之后才被执行,这个闭包可以采用逃逸闭包实现。逃逸闭包里需显式引用self。
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// 打印出 "200"
completionHandlers.first?()
print(instance.x)
// 打印出 “100"