Swift- Closures 闭包 & 尾随闭包学习笔记

2,549 阅读3分钟

闭包

闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的匿名函数(Lambdas)比较相似。

Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进行语法优化,主要优化如下:

  • 利用上下文推断参数和返回值类型
  • 隐式返回单表达式闭包,即单表达式闭包可以省略 return 关键字
  • 参数名称缩写
  • 尾随闭包语法

0. 闭包表达式语法

闭包表达式语法有如下的一般形式:

{ (parameters) -> return type in
    statements
}

1.创建基本的闭包

简单创建一个变量,创建一个函数赋值给一个变量

let driving = {
    print("I'm driving in my car")
}
driving()

2. 在闭包接受参数

let driving = {(_ place: String) in 
    print("I'm going to \(place) in my car")
}
driving("BeiJing")

3. 在闭包返回参数

let drivingWithReturn = {(place: String) -> String in 
    return "I'm going to \(place) in my car"
}
let message = drivingWithReturn("London")
print(message)

4. 闭包作为参数

因为闭包可以像字符串和整数一样使用,所以可以将它们传递给函数。 有点绕,写多了就会了

func travel(action:(_: String) -> String) {
    print("I'm getting ready to go,")
    let message = action("Beijing")
    print(message)
    print("I'm arrived!")
}
travel(action: drivingWithReturn)

5. 尾随闭包语法

如果你需要将一个很长的闭包表达式作为最后一个参数传递给函数,将这个闭包替换成为尾随闭包的形式很有用。尾随闭包是一个书写在函数圆括号之后的闭包表达式,函数支持将其作为最后一个参数调用。在使用尾随闭包时,你不用写出它的参数标签:

为了证明这一点, 写一个travel()功能,接受action 闭包参数,以便可以打印两个print()调用之间运行

func travel(action: () -> Void) {
    print("I'm getting ready to go.")
    action()
    print("I arrived!")
}

实际上,由于没有任何其他参数,我们可以完全消除括号:

travel {
    print("I'm driving in my car")
}

6. 当闭包接受参数时,将其用作参数

func travel(action: (String) -> Void) {
    print("I'm getting ready to go.")
    action("London")
    print("I arrived!")
}
travel { (place: String) in
    print("I'm going to \(place) in my car")
}

//  返回值时使用闭包作为参数
func travel(action: (String,String) -> String) {
    print("I'm getting ready to go.")
    let description = action("Beijing","London")
    print(description)
    print("I arrived!")
}
travel{(a: String, b: String) in 
    return "I'm going to \(a) and \(b) in my car"
}

6. 为什么Swift有尾随的闭包语法?

尾随闭包可以让Swift 的代码更加容易读,尽管学习起来比较吃力,

但理解之后感觉还是挺香的;可以简化很多OC时代的复杂写法

还记得我们写Objective-C的时候,经常写UIView的动画函数;

[UIView animateWithDuration:1.5 animations:^{
       <#code#>
} completion:^(BOOL finished) {
       <#code#>
}];

而现在 Swift 写法更加简洁

UIView.animate(withDuration: 1.5, animations: {
    print("animation block")
}, completion: { (finished: Bool) in
    print("I'm getting ready to go \(finished)")
})

animations 都可以省略

UIView.animate(withDuration: 1, delay: 1, options: .curveEaseIn) {
    print("animaitons block")
} completion: { (a:Bool) in
    print("completion")
}

这样尾随闭包的含义直接附加到了函数名称上