swift闭包

一.基础概念

  1. 闭包表达式:可以用func定义一个函数,也可以用闭包表达式来定义一个函数。闭包表达式不需要写外部名称,在外部使用时直接传入参数。
//闭包表达式
{
	(参数列表) -> 返回值类型 
	in
	函数体代码
}
  1. 尾随闭包:将闭包表达式作为参数的最后一个实参,用尾随闭包来增加函数可读性。将闭包写在小括号外: test(a:Int,b:Int){$0 + $1} 。如果闭包是唯一参数,则可以写作 test{$0 + $1},意义是调用test,并且传入这个闭包。
  2. 忽略参数:不使用参数时候用_ 代替。
  3. 闭包:(Closure),一个函数(一般指定义在函数内部的函数)和它捕获的变量\常量(捕获的是外层函数的局部变量\常量)组合在一起,称为闭包。
  4. 捕获:如果是局部变量执行完之后生命周期就应该结束,但是如果闭包使用了外层函数的局部变量/常量,则会把这个值放入堆空间中,在后续的操作中不会用完就销毁。
typealias Fn = (Int) -> Int
func getFn() -> Fn{
    var num = 0
    //当num没有被plus调用时候,是放在栈里
    //当num被plus调用后,放在堆中,所以下面的四次调用访问的都是堆空间的
    func plus(_ i:Int) -> Int{
        num += i
        return num
    }
    return plus
}
var fn1 = getFn() //调用一次只分配一次堆空间
print(fn1(1)) // 1
print(fn1(2)) // 3
print(fn1(3)) // 6
print(fn1(4)) // 10
//所有fn1调用完毕以后重新初始化,初始化的值由num的值来确定。
var fn2 = getFn()
print(fn2(5)) // 5
print(fn2(6)) // 11
print(fn2(7)) // 18
print(fn2(8)) // 26
//堆空间需要多少内存:首先申请堆空间内存时候应该会给alloc传入一个参数,
//传达这个值需要多少堆空间。
//所以在汇编中寻找申请前传入了什么参数,比如rdi,rsi,rdx等
//堆空间前16存储了这个值类型的地址和引用计数,然后类型需要多少位
//之后以16的倍数补齐。
  1. 闭包可以当作一个类的实例对象,内存在堆空间,捕获的局部变量\常量就是对象的成员,组成闭包的函数就是类内部定义的方法。
  2. 把一个函数赋值给一个变量,内存中占16字节,前8位放直接调用的函数地址值,后8位放0。
  3. 把一个闭包赋值给一个变量,前8字节放一个间接调用的函数地址,去向闭包中的函数,后8字节放一个堆空间的地址值,这个地址指向的是函数捕获的外部参数。
  4. 在AT&T中,间接调用是call 后接一个寄存器地址,且地址前有一个*(星号)。
  5. 闭包的捕获在调用闭包之前就已经把变量传到堆空间了,且是编译时需要明确闭包要被返回才是被捕获的,可以视作捕获是在return时候捕获的。
  6. 为捕获变量申请堆空间的目的是保住这个变量的生命周期,当调用的变量如果是一个全局变量的话,那在程序运行中变量都存在数据段中,就不需要申请堆空间为期保命了,也就不会发生捕获的过程,严格来说调用一个全局变量就不是闭包了。
  7. 捕获多个外部变量的时候,每个外部变量都有个属于自己独立的堆空间,都有自己的类型,引用计数,数据的空间。
  8. 多个函数捕获同一个外部变量且只有一次函数调用的情况下,外部变量的堆空间是共享用的。
  9. 自动闭包:@autoclosure,自动将传入值生成闭包表达式,只支持 ( )->T的函数形式。有无@autoclosure的同名函数构成函数重载。自动闭包的代码载空合运算中会延迟调用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值