1. Block简述
Block是将函数
及其执行上下文
封装起来的对象
.
1 | struct __block_impl { |
Block调用即函数的调用
1 | { |
2. 截获变量
- 对于
基本数据类型
的局部变量
截获其值. - 对于
对象类型
的局部变量``连同所有权修饰符
一起被截获. - 以
指针形式
截获局部静态变量. (故可以避免值被截获,而导致的与目的相违背) 不截获
全局变量, 静态全局变量.
3. __block修饰符
- __block的作用是可以获取对应变量的指针,使其可以在block内部被修改.
- 一般情况下,对被截获变量进行赋值操作需添加__block修饰符. (注意:
赋值不等于使用
.) - 在对变量进行赋值时, 对局部变量(1. 基本数据类型, 2.对象类型)需要添加
__block
修饰符; 对(1.静态局部变量, 2.全局变量, 3.静态全局变量)不需要__block
修饰符. - __block修饰后的变量变成了
对象
.
4. Block的内存管理
_NSConcreteStackBlock
(栈block, 栈; copy操作后堆上面产生block)_NSConcreteMallocBlock
(堆block, 堆, copy操作后增加其引用计数)_NSConreteGlobalBlock
(全局block, 已初始化数据区, copy操作后什么也不做)
栈上面Block的销毁
__forwarding存在的意义
不论在任何内存位置, 都可以顺利的访问同一个__block变量.(堆上面的)
5. Block的循环引用
自循环引用
1 | _array = [NSMutableArray arrayWithObject: @"block"]; |
解决 =>
1 | _array = [NSMutableArray arrayWithObject: @"block"]; |
Blcok循环引用
案例:
1 | __block Block *blkSelf = self; |
MRC
下正常, __block
修饰对象不会增加其引用计数;ARC
下有循环引用, 会引起内存泄露,__block
修饰对象会被强引用,无法避免的循环引用,需手动断环
.
案例分析:
当前对象持有 block, block又持有block变量,而block变量又持有当前对象,所以形成一个大环.
如果是有__block修饰的循环引用,可以采取”断环”操作,消除循环引用,但是如果block一直没有调用的话, 这个循环引用还是会一直存在.
1 | __block Block *blkSelf = self; |
总结
什么是Block?
函数及其执行上下文的封装的对象
为什么Block会产生循环引用?1. 自循环, 2. __block大环循环引用(对象->block->__block->对象)
Block截获变量的特性?
1.区分局部/全局变量, 2.静态
循环引用类型, 如何解决?
1.避免循环, 2.断环处理
- 本文作者: 醉疏狂
- 本文链接: https://hubin97.github.io/2020/05/20/Block/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!