问题 1:什么是 Block?
关于这个问题,有位大神是这么说的,将函数及其执行上下文封装起来的对象,就叫做 Block。
问题 2:什么是 Block调用?
Block调用实际上就是函数的调用。
问题 3:Block的截获变量特性是怎么样的?
针对不同类型的变量,Block的截获特性也是不一样的。
- 基本数据类型的局部变量 Block 可以截获其值
- 对于对象类型的局部变量连同所有权修饰符一起截获
- 局部静态变量以指针的形式进行截获
- 全局变量和静态全局变量,block 是不截获的
问题 4:什么时候需要使用__block?
一般情况下,对被截获变量进行赋值操作时需要使用__block 修饰符。
追问1:什么时候不需要使用__block 也能对变量进行赋值?什么情况下是需要使用的呢?
根据 block 的截获特性进行回答
追问 2:为什么通过__block 修饰的变量可以截获?(__forwarding 指针,分别针对栈上的 block 和堆上的 block 进行分析)
通过__block 修饰的变量最终会经系统编译成为一个结构体,结构体中有一个 isa 指针,和一个什么的值以及__forwarding 指针,经过修饰以后,我们调用赋值操作其实就会转变为 a.__forwarding->a = x。详细的参看
https://blog.csdn.net/u014600626/article/details/78697535
追问 3:__forwarding指针是用来干什么的?
无论在任何内存位置,都可以通过__forwarding指针获取 同一个__block 的变量。
问题 5:什么时候需要对 block 进行 copy 操作?
问题 6:以下的代码有什么问题?(如何解决?为什么?)
问题 7:以下的代码有什么问题?
- 在 MRC的环境中不会产生循环引用
-
在 ARC的环境中会产生循环引用
追问:在 ARC 环境中为什么会产生循环引用,MRC中为什么不会?如何解决循环引用?
解决方案,采用段环的形式,在 block 内部将__block 修饰的变量置为 nil,这样在调用的时候就断开了对原对象的持有关系,从而达到规避循环引用的问题,但是这种解决方案有一个小弊端,就是如果 block 不被调用,那么循环引用的环就会一直存在。
网友评论