在 swift中可以用 func 定义一个函数,也可以用闭包表达式定义一个函数
- func sum(v1:Int, v2:Int) -> Int { v1 + v2 }
- let sum2 = { (v1:Int, v2:Int) -> Int in
- return v1 + v2
- }
- sum(v1: 10, v2: 20)//func定义的函数
- sum2(10, 20)//闭包表达式定义的函数
- func sun(param1:Int, param2:Int, test:( Int, Int) -> Int) {
- print(test(param1, param2))
- }
-
- sun(param1:20 , param2:20, test:{
- (v1:Int, v2:Int) -> Int in
- return v1 + v2
- })
- //闭包表达式简写
- sun(param1:20 , param2:20, test:{
- v1, v2 -> Int in
- return v1 + v2
- })
- sun(param1:20 , param2:20, test:{
- v1, v2 in
- return v1 + v2
- })
- //闭包表达式隐式返回
- sun(param1:20 , param2:20, test:{
- v1, v2 in v1 + v2
- })
- //参数名称简写
- sun(param1:20 , param2:20, test:{
- $0 + $1
- })
- //函数式闭包
- sun(param1: 2, param2: 3, test: +)
最后一个参数是闭包表达式的时候,可以独立于前面的参数,写在函数参数外面的闭包表达式,使结构看起来再加清晰整洁,属于结构优化,默认闭包表达式作为参数的时候采用尾随闭包的形式。
- sun(param1: 12, param2: 13) { (v1:Int, v2:Int) -> Int in
- return v1 + v2
- }
- //尾随闭包表达式
- sun(param1: 12, param2: 13) { v1, v2 in
- v1 + v2
- }
- //尾随闭包表达式简写
- sun(param1: 20, param2: 12) { return $0 + $1 }
- //尾随闭包表达式简写
- sun(param1: 10, param2: 12) { $0 + $1 }
- sun(param1: 10, param2: 12) { $0 + $1 }
-
- sun(param1: 2, param2: 3, test: +)
顾名思义根据传入的参数,自动生成闭包;延迟执行,属于性能优化,除些之外也属于结构优化,调用者无需关心参数类型,用@autoclosure 修饰。
@autoclosure 只支持()->T 的格式参数,并且不仅仅只支持最后一个参数。
系统的合并运算符??属于自动闭包。
自动闭包允许你延迟处理,因此闭包内部的代码直到你调用它的时候才会运行。
- //添加 @autoclosure 关键字, 当闭包被调用的时候,会返回被包装在其中的表达式的值
- public func assert(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line) {
- if !condition() {
- print(message())
- }
- }
- let number = 3
- assert(number > 3, "number 不大于3") //输出: number 不大于3
- //自动闭包允许延迟处理
- var person = ["zhangsan", "lisi", "wangwu", "zhailiu"]
- print(person.count) // 输出: 4
- let deletePerson = { person.remove(at: 0) }
- print(person.count) //此时输出还是 4,因为没有调用闭包没有被调用,闭包里的代码没有被执行
-
- //此时调用闭包
- print(deletePerson()) //输出 "zhangsan"
- print(person.count) //输出: 3
- //闭包作为实际参数传递给函数时,能获得同样的延时求值行为
- //闭包作为实参, 可以显示的使用闭包
- var person = ["zhangsan", "lisi", "wangwu", "zhailiu"]
- func serve(customer customerProvider: () -> String) {
- print("Now serving \(customerProvider())!")
- }
- //函数接受一个返回顾客名字的显式的闭包
- serve(customer: { person.remove(at: 0) }) //打印: Now serving zhangsan!
- //自动闭包作为实际参数
- var person = ["zhangsan", "lisi", "wangwu", "zhailiu"]
- //customerProvider 参数将自动转化为一个闭包,因为该参数被标记了 @autoclosure 特性
- func serve(customer customerProvider: @autoclosure () -> String) {
- print("Now serving \(customerProvider())!")
- }
- serve(customer: person.remove(at: 0)) //打印: Now serving zhangsan!
- //自动闭包允许逃逸,同时使用 @autoclosure 和 @escaping 标志
- var customerInLine = ["zhangsan", "lisi", "wangwu", "zhaoliu"]
- var customerProviders: [() -> String] = []
- func collectionCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
- customerProviders.append(customerProvider)
- }
- print(customerProviders.count) //打印: 0
- collectionCustomerProviders(customerInLine.remove(at: 0))
- collectionCustomerProviders(customerInLine.remove(at: 0))
- print(customerInLine.count) //打印: 4
- print(customerProviders.count) //打印: 2
-
- for c in customerProviders {
- print("Now serving \(c())")
- }
- /*
- Now serving zhangsan
- Now serving lisi
- */
collectCustomerProviders(_ : ) 函数并没有调用传入的 customerProvider 闭包,而是将闭包追加到了 customerProviders 数组中。
这个数组定义在函数作用域范围外,这意味着数组内的闭包能够在函数返回之后被调用。
因此,customerProvider 参数必须允许“逃逸”出函数作用域。
- 闭包可以对外部函数的变量、常量进行捕获;
- 闭包捕获时机是在函数执行完,return 时再去捕获
- 当函数里有多个闭包时,只会对变量、常量捕获一次,多个闭包对捕获的变量、常量共享
- 闭包不会对全局变量进行捕获
闭包可以在其被定义的上下文中捕获常量或者变量。即是定义这些常量和变量的原作用域已经不存在了,闭包仍然可以在闭包函数体内引用和修改这些值。
和类一样,闭包也是引用类型
闭包和闭包表达式并不一是一个东西,半包表达式是函数的另外一种定义,而闭包是一个函数和它所捕获变量/常量环境的组合;
一般指定义在函数内部的函数;一般它捕获的是外层函数的局部变量/常量;
闭包和和闭包表达式的区别?
闭包表达式是:函数的另外一种表现形式,为了实现简介和高效,有不同的表现形式,例如自动闭包,尾随闭包;
闭包是:封装在函数中的函数或者闭包表达式,且捕获了局部变量的运行环境。它运用了闭包表达式,但闭包表达式不是闭包。
objective-c解决闭包的循环引用问题一般是先声明
__weak typedef(weakSelf) = self;
然后使用weakSelf对本类的属性调用。
swift中也有类似于objective-c中的方法:首先是声明:weak var weakSelf = self;
然后使用weakSelf对本类的属性调用。self可能会为nil,所以需要用var。
在objective-c中,我们通常使用__block来声明一个变量,这样就可以在闭包内对这个变量进行修改。
在swift中没有__block这种关键字,但是swift中的闭包是做了优化处理,是可以直接捕获上下文中的变量。所以可以直接在闭包中对变量进行修改。