Block相关知识
2019-10-16 本文已影响0人
huoshe2019

一、Block本质
1.1、概念
Block是将函数及其执行上下文封装起来的对象。
问题1:什么是Block?
Block是将函数及其执行上下文封装起来的对象。

问题2:什么是Block调用?
Block调用就是函数调用。
1.2、代码转换指令

二、Block截获变量
问题2:截获变量面试题

答案是12。
2.1、截获变量类型分类


问题3:关于Block的截获变量特性怎么理解?
从截获类型和截获特性进行解释(见上图)。
三、__block修饰符
3.1、赋值和使用的区别
使用
不需要使用__block

赋值
需要使用__block

3.2、使用场景细分
问题4:什么场景使用__block修饰符?



问题5:__block笔试题

解释原因:
1、__block修饰的变量变成了对象,如下:

2、后面使用的multiplier都是结构体里面的,通过forwarding指针引用,如下:

3、又因为在Block在栈上,__block的forwarding指针指向自己,如下图:

4、所以这里修改的multiplier也就是修改栈上的变量。而Block在栈上,所以使用的也是栈上的变量。
补充:__block在ARC和MRC区别
- MRC 环境下,block 截获外部用 __block 修饰的变量,不会增加对象的引用计数
- ARC 环境下,block 截获外部用 __block 修饰的变量,会增加对象的引用计数
四、Block内存管理
4.1、Block类型

4.2、Block内存区域

4.3、Block的Copy操作

注意:
对Block的Copy操作理解,会将Block从栈放到堆上,防止使用的时候,Block被销毁。
所以,一般声明的Block成员变量关键字是Copy。
4.4、栈上Block的销毁

4.5、栈上Block的Copy
问题6:当把栈上的Block进行Copy操作之后,在MRC环境下,是否会引起内存泄漏?
是的
4.6、栈上__block变量的Copy

所以一旦被Copy到堆上,即使代码表面上是修改栈上的__block变量,其内在本质是修改堆上的__block变量。
例题实战

- _blk进行了Copy操作,里面的multiplier用的是堆上的。
- multiplier = 6其实是通过栈上的forwarding修改堆上的multiplier。
- 结果是 4 * 6 = 24。
4.7、forwarding指针总结

- 如果没有对__block进行Copy操作,就是操作栈上的__block变量。
- 如果发生了Copy操作,无论是在栈上还是在堆上,都是操作堆上的__block变量。
五、Block循环引用问题
问题7:以下代码有什么问题?

有循环引用。
原因:
- 根据Block截获变量的特性,对于对象,会将所有权修饰符一起截获。
- 这里对象持有Block,又因为array是strong,所以Block对array也是strong。
解决办法:

- 也是从截获变量特性解释
问题8:以下代码有问题吗?

答案:

解释:
在ARC情况下

解决办法:

问题9:为什么Block会产生循环引用?
从截获变量特性进行答题
问题10:怎样理解Block截获变量对特性?

问题11:你遇到过哪些循环引用?你又是怎样解决的?
- NSTimer
- Block