Block底层学习

1、本质

  • 是一个oc对象,它内部有isa指针;继承于NSObject;比如可以通过调用class方法查看block的类型
  • Block是封装了函数调用以及函数调用环境的oc对象

2、 block的数据结构

Funcptr为函数调用地址,这里的age为block截取外部的变量

Desc为描述信息结构体,block_size为block的大小

block的调用时候实质是funcptr的实现

3、block的变量捕获

为了保证block内部能正常使用外部变量,block有个捕获机制

  • 对于局部基本数据变量捕获是值捕获(作用域的原因,不能保证局部变量什么时候释放);static局部变量是指针捕获,
  • 全局变量不会捕获,直接取值;(因为谁就可以访问到)
  • Oc对象的捕获连同修饰词一起捕获

4、block三种类型

可以通过block调用class或者isa指针查看block的类型,最终都继承于NSBlock

  • 全局区(数据区、data区)block  _NSConcreteGlobalBlock : 不捕获外部变量的block(可以使用全局变量,因为只是取值没有捕获)
  • 栈区block _NSConcreteStackBlock:捕获外部变量,
  • 堆区block  _NSConcreteMallocBlock_NSConcreteStackBlock  copy得到

5、block的三种类型的copy操作

  • 全局copy什么也不做
  • 栈区copy得到堆区block
  • 堆区copy 引用引用计数器加一

  • 如果block在栈区,将不会对auto变量产生强引用
  • 栈区block进行copy生成堆区block的时候,底层会自动调用一个叫_block_object_assign的函数,这个函数会根据auto变量的修饰符(__strong、__weak、__unsafe_unretained)做出操作,类似retain(形成强引用、弱引用)
  • 堆区block的移除,block内部执行dispose函数,dispose函数内部会调用_block_object_dispose函数,该函数会自动释放引用的auto变量,类似于release操作

ARC下编译器会根据情况自动将栈block进行copy,以下情况会触发copy

  • Block做为函数返回值
  • 将block赋给 __strong 指针的(强引用的时候)时候
  • 一些foundation框架中的函数block
  • GCD 里面的block

6、block修改外部变量、__block

  • 全局、局部static  变量可以更改(变量一直存在内存中,不可取)
  • 局部临时变量使用__block修饰,(__block不能修饰全局、static变量)

__block修饰变量本质:编译器会将__block变量包装成一个对象,对象结构体内部有被修饰的变量和__foewarding指针;内部也会通过_block_object_assign进行强引用(MRC不会强引用),_block_object_dispose函数进行释放操作;

注意: Block操作可变数组的时候,不需要添加__block,

7、block的循环引用问题

对象持有block 、block持有了对象 ;形成循环引用

解决的方案:

__weak: 对象释放 ,指针置为nil

__unsafe_unretained:  对象释放 ,指针不会置为nil

__block:  要自己将持有对象赋空

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值