Swift闭包(Closure)

139 阅读2分钟

Swift相关:

1、闭包的定义

一个函数和它所捕获的变量常量环境组合起来,被称为闭包

注意:

  • 这里的函数一般指定义在函数内部的函数
  • 一般捕获的是外层函数的局部变量、常量
func makeClosure() -> (Int) -> Int {
    var temp = 1
    func closure(_ number:Int) -> Int { 
        temp += number 
        return temp 
    } 
    return closure //返回的makeClosure和one形成了闭包
}
  • 内存在堆空间
  • 捕获的局部变量、常量就是对象的成员(存储属性)
  • 组成闭包的函数就是类内部定义的方法

闭包是自包含的功能代码块,跟COC中的代码块(block)和其他一些语言中的匿名函数相似

  • 闭包可以作为函数的参数也可以作为函数的返回值
  • 可以向OC中一样用于回调和反向传值

2、闭包表达式

{(param1, param2) -> (returnType) in
        // code
}
  • 参数有多个时,多个参数用逗号隔开
  • 参数列表的小括号可以省略
  • 返回值类型也可以省略
  • 当没有返回值是in可以省略
  • in可以看做是一个分隔符,将函数体和前面的参数、返回值分隔开

2.1、闭包作为变量或常量

var closure1: (_ num1: Int, _ num2: Int) -> Int = {(num1, num2) -> Int in
        return num1+num2
}
let closure2: (_ num: Double) -> Double = { num -> Double in
        return num
    }
var x = closure1(10, 20)
var y = closure2(200.0)
var closure : (Int) -> Int?         // 错误

var closure : ((Int) -> Int)? = nil // 正确

2.2、闭包作为函数的参数

func closureFunc(param:(_ num1: Int, _ num2: Int) -> Int) {
    print("ret:\(param(100, 200))") // 100
}

closureFunc(param: {(num1, num2) -> Int in
    print("\(num1),\(num2)")
    return num1+num2
})

2.3、闭包作为返回值

var closure: (_ a: Int) -> Int
func closureFunc(_ a: Int, _ b: Int) -> (_ a: Int) -> Int {
    return closure
}

3、尾随闭包

当我们把闭包表达式作为函数的最后一个参数,如果当前的闭包表达式很长,我们可以通过尾随闭包的书写方式来提高代码的可读性

func closureFunc(_ a: Int, _ b: Int, _ by:(_ x:Int) -> Int) {
     var num = by(20)
}

closureFunc(20, 20){ x in
     return x
}

var array = [1, 2, 3]
array.sort(by: {(item1 : Int, item2: Int) -> Bool in return item1 < item2 })
array.sort(by: {(item1, item2) -> Bool in return item1 < item2 })
array.sort(by: {(item1, item2) in return item1 < item2 })
array.sort{(item1, item2) in item1 < item2 }
array.sort{ return $0 < $1 }
array.sort{ $0 < $1 }
array.sort(by: <)

4、闭包捕获值

func make() {
    var i = 1
    let closure: (_ a: Int) -> () = { a in
        i += a
        print("closure:\(i)")
    }
    print(i)
    closure(1)
    print("after1:\(i)")
    closure(1)
    print("after2:\(i)")
}
make()

//输出结果
1
closure:2
after1:2
closure:3
after2:3

在闭包调用捕获外部局部变量的时候,是把值捕获到了堆区,在使用的时候直接访问地址拿到的值。

  • 闭包可以在方法调用的时候捕获上下文中的常量或变量。
  • 即使这个方法的作用域已经不在,仍然可以修改捕获到的变量

4.1、全局变量和局部变量捕获时的区别

闭包在使用全局变量的时候不会捕获到闭包内部,而在使用局部变量的时候会捕获到闭包的内部再使用