Swift 闭包底层探究

闭包

闭包:一个函数和它所捕获的变量\常量环境组合起来,称为闭包
(一般它捕获的是外层函数的局部变量\常量)

  • 可以把闭包想象成是一个类的实例对象
    • 捕获的局部变量\常量就是对象的成员(存储属性)
    • 组成闭包的函数就是类内部定义的方法
func getFn() -> (Int) -> Int {
    var num = 0
    return { 
        num += $0;
        return num;
    }
}

var fn = getFn() // malloc堆地址 将外部变量num存入
print(fn(1)) // 1
print(fn(2)) // 3
print(fn(3)) // 6
print(fn(4)) // 10

print(getFn()(1)) // 1  malloc
print(getFn()(2)) // 2  malloc
print(getFn()(3)) // 3  malloc
print(getFn()(4)) // 4  malloc

反汇编查看

  • 将局部变量注掉,观察运行过程中并没有调用 swiftallocObject,并没有向堆空间申请地址。


  • 使用局部变量时,闭包内部需要捕获外部的局部变量/常量,存储在堆空间中。 打印 rax,获取闭包在堆空间保存变量的地址的位置。


  • 将断点打在 num 变化处,去堆空间地址中查看存储数值是否发生改变,若能对应得上,则证明猜想正确。


练习

typealias Fn = (Int) -> (Int, Int)

func getFns() -> (Fn, Fn) {
    // 分别创建两个地址保存,但数据是共用的
    var num1 = 0 // malloc num1
    var num2 = 0 // malloc num2
    func plus(_ i: Int) -> (Int, Int) {
        num1 += i
        num2 += i << 1    // *2
        return (num1, num2)
    }
    func minus(_ i: Int) -> (Int, Int) {
        num1 -= i
        num1 -= i << 1
        return (num1, num2)
    }
    return (plus, minus)
}
// 把闭包想象成是一个类的实例对象,捕获的局部变量\常量就是对象的成员
let (p, m) = getFns()
print(p(5)) // (5, 10)
print(m(4)) // (1, 2)
print(p(3)) // (4, 8)
print(m(2)) // (2, 4)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容