Block的本质
- Block是将函数及其上下文封装起来的对象
Block调用
- Block调用就是函数的调用
截获变量
-
局部变量
1.基本数据类型
2.对象类型 -
全局变量
-
静态局部变量
-
静态全局变量
关于Block截获变量的特性,是否有理解?
- 对不同的数据类型,截获方式各有不同
1.对基本数据类型的局部变量截获其值
2.对于对象类型的局部变量连同所有权修饰符一起截获
3.以指针方式截获静态局部变量
4.不截获全局变量、静态全局变量
在什么场景下使用__block修饰符呢?
-
对截获变量进行赋值操作需要添加__block修饰符(赋值 != 使用)
-
对局部变量(基本数据类型和对象类型)进行赋值需要__block修饰符
-
对静态局部变量、全局变量、静态全局变量不需要__block修饰符
使用操作,不需要__block修饰
赋值操作,需要添加__block修饰符
添加__block修饰后,结果为8
__block修饰符起到了什么作用?__block的机制是什么?
- __block修饰变量变成了对象
Block的内存管理
- _NSConcreteGlobalBlock
- _NSConcreteStackBlock
-
_NSConcreteMallocBlock
不同类型的block
三种类型的block存储区域
需要在什么时候对block进行copy操作?
- 首先明白三种类型的block进行copy有什么效果
- 对于数据区的block进行copy操作,什么也不做
- 对于栈区的block进行copy操作,在堆区产生block
- 对于堆区的block进行copy操作,会增加引用计数
- 生命周期
-
对于栈区的block,变量作用域结束,随之销毁
在MRC环境下,对栈区的block进行copy操作,不作处理会产成内存泄漏
__forwarding总结
- 不管在任何内存位置,都可以顺利的访问同一个__block变量
Block循环引用(为什么会产生循环引用)在下图中,有什么问题?如何解决?
示例- 产生自循环引用 因为当前对象通过copy声明block,而在当前block中又使用到了当前对象的成员变量,因为会连带属性关键字一起截获,因为array是通过strong修饰,因此block中有一个strong类型的指针指向当前对象,产生循环引用
- 解决方法:避免循环引用——在当前栈中用__weak修饰的weakArray指针指向原对象的_array,在block中使用weakArray(因为截获的是一个__weak类型)
(__block造成的循环引用)在下图中,有什么问题?如何解决?
示例- 在MRC中,不会产生循环引用
-
在ARC中,产生循环引用,引起内存泄漏
解决方案,断环 但是如果一直不调用block,环就一直存在
网友评论