- Block介绍
- 截获变量
- __block修饰符
- Block的内存管理
- Block的循环引用
一、Block介绍
1.什么是Block
- Block是将函数及其执行上下文封装起来的对象
写法:
2、Block 的调用
- Block的调用就是函数的调用
二、截获变量
问题:这个结果为什么是12
1.变量的分类
- 局部变量(基本数据类型、对象类型)
- 静态局部变量
- 全局变量
- 静态全局变量
2.针对不同变量的截获
- 对基本数据类型的局部变量截获其值
- 对对象类型的局部变量连同所有权修饰符一起截获
- 以指针形式截获局部静态变量
- 不截获全局变量、静态全局变量
三、__block 修饰符
什么情况下使用:
- 一般情况下,对被截获变量进行赋值操作需要添加 __block 修饰符(赋值 不是 使用)
(需要)
(不需要)
对变量进行赋值时:
- 局部变量(基本数据类型、对象类型),都需要 __block 修饰
- 静态局部变量、全局变量、静态全局变量,不需要__block 修饰
__block 修饰的的变量变换成了对象
四、Block 的内存管理
Block的类型:
- 全局的 -- _NSConcreteGlobalBlock
- 栈上的 -- _NSConcreteStackBlock
- 堆上的 -- _NSConcreteMallocBlock
不同类型 Block 的位置:
Block 的 Copy 操作
1.栈上 Block 的销毁
2.栈上 Block 的 Copy (栈上的 Block释放时,MRC 下会引起内存泄漏,因为堆上的 Block 不会进行销毁)
3.栈上 __block 的变量 Copy
3. __forwarding 存在的意义
- 不论在任何内存位置,都可以顺利的访问同一个__block 变量。
五、Block 的循环引用
例1:
问题:
解决方案:
原理:对对象类型的局部变量连同所有权修饰符一起截获,而数组一般是用 strong 修饰,所以会引起循环引用,而改成 __weak 之后,为弱引用,所以不会引起循环引用
例2:
问题:
答案:
- MRC下,不会产生循环引用
- ARC下,会产生循环引用,引起内存泄漏
分析,ARC 下:
解决方案:
缺陷:
若 Block 一直未被调用,则循环引用会一直存在
六、总结
- 什么是 Block?
- 为什么 Block 会产生循环引用?(如果当前 Block 对当前对象进行截获,则会对当前对象有强引用,又当前对象强引用 Block ,所有会产生自循环引用,可用 __block 修饰截获变量解决;;__block 修饰在 ARC 下循环引用,方法见上文)
- 怎样理解 Block 截获变量的特性?
- 你都遇到过哪些循环引用?你是怎样解决的?