1.闭包的定义和调用:
_ = { (param1: Int, param2: Float, param3: Void) -> return_type in // 闭包执行代码 /* ... */ }
// 这里声明了一个函数类型的引用指向闭包 // 其类型为:(Int, Int) -> () -> Void let ref = { (a: Int, b: Int) -> () -> Void in let sum = a + b var x = sum * 2 // 这里在一个闭包内定义了一个嵌套闭包, // 其参数列表为空,返回类型为Void return { () -> Void in // 在此嵌套闭包中捕获了其外部闭包的sum常量 // 以及x变量 print("x = (x), sum = (sum)") x += sum } }
ref(a: 100, b: 200) // x = 600, sum = 300
2.闭包表达式的简略表达:
3.尾随闭包:
“如果一个闭包表达式作为函数调用的最后一个实参,那么我们可以采用尾随闭包(trailing closures)语法糖。当我们采用尾随闭包语法时,如果该函数最后一个形参带有实参标签,那么该实参标签也被省去。”
摘录来自: “大话Swift 4.0”。 iBooks.
func foo(callback: () -> Void) { callback() } // 如果一个函数只有一个形参,并且为函数类型, // 那么我们在使用尾随闭包时连函数调用操作符也可缺省 foo { print("This is a closure") }
我们看到,如果在一个函数调用最后使用了尾随闭包,这个函数调用看上去十分像一个函数定义。所以我们在读代码的时候需要看所调函数之前有没有关键字 func,如果有 func 说明这是一个函数定义,没有则说明是函数调用。
4.捕获局部变量与闭包的执行上下文:
5.逃逸闭包:
“定义了一个函数,它有一个形参为函数类型,如果在此函数中将通过异步的方式调用该函数引用对象,那么我们需要将此函数类型声明为逃逸的(escaping),以表示该函数类型的形参对象将可能在函数调用操作结束后的某一时刻才会被调用。我们要声明一个函数类型的形参为一个逃逸类型非常简单,只需要在类型前加 @escaping 类型说明符即可。”
摘录来自: “大话Swift 4.0”。 iBooks.
// 这里声明了一个隐式拆解的Optional函数引用对象ref, // 其初始值为空 var ref: (() -> Void)! /// 这里定义了一个函数foo, /// 它仅有一个形参closure /// - parameter closure: 类型为:@escaping () -> Void /// 这里如果不加@escaping类型说明符,那么会出现以下编译报错: /// 将非逃逸的形参'closure'赋值给一个逃逸的闭包 func foo(closure: @escaping () -> Void) { // 这里仅仅是将形参closure赋值给我们上面定义的ref函数引用对象 ref = closure } // 调用foo函数,并给出一个简单的闭包 foo { print("Hello, world!") } // 这里是在调用了foo函数之后再通过ref去调用传递给它的闭包对象 […]
6.自动闭包:
“如果一个函数的某个形参为函数类型,并且它不含任何形参,那么我们可以将此参数声明为自动闭包(autoclosure)。如果要将一个形参声明为自动闭包,那么在该形参的类型前加 @autoclosure 类型说明符即可。当一个形参作为一个自动闭包时,我们在调用该函数所传入的实参只需要一个表达式即可,Swift编译器会自动将它封装为一个闭包表达式。”
摘录来自: “大话Swift 4.0”。 iBooks.
// 这里再次定义了函数foo, // 将它的函数类型的形参声明为自动闭包 func foo(auto closure: @autoclosure () -> Void) { closure() } // 我们看到,这里对foo调用时, // 形参直接就传入了一个函数调用表达式 foo(auto: print("This is a simple lambda!"))