什么是Block
Block是将函数及其执行上下文封装起来的对象。
__block修饰符
一般情况下,对被截获变量进行赋值操作需要添加__block修饰符
对变量进行赋值时
Block 的几种形式
分为全局Block( )、栈Block(_NSConcreteStackBlock)、堆
Block( )三种形式
其中栈 Block 存储在栈(stack)区,堆 Block 存储在堆(heap)区,全局 Block 存储在已初始化数据(.data) 区
不使用外部变量的 block 是全局 block
使用外部变量并且未进行 copy 操作的 block 是栈 block
对栈 block 进行 copy 操作,就是堆 block,而对全局 block 进行 copy,仍是全局 block
Block的copy操作
问题1:由于block捕获的__block修饰的变量会去持有变量,那么如果用__block修饰self,且self 持有 block,并且 block 内部使用到__block 修饰的 self 时,就会造成多循环引用,即 self 持有 block, block 持有__block 变量,而__block 变量持有 self,造成内存泄漏。
如果要解决这种循环引用,可以主动断开__block 变量对 self 的持有,即在 block 内部使用完 weakself 后,将其置为 nil,但这种方式有个问题,如果 block 一直不被调用,那么循环引用将一直存在。 所以,我们最好还是用__weak 来修饰 self
Block面试总结
问题1:什么是block?
Block是将函数及其执行上下文封装起来的对象。
问题2:为什么block会产生循环引用?
1:如果当前block对当前对象的某一成员变量进行截获,这个block会对对应变量强引用,当block又由于当前对象对其有一个强引用,产生了一个自循环引用方式的问题。
答:我们可以通过声明其为__weak变量进行循环引用的消除。
2:如果定义了一个__block声明符的话那么也会产生循环引用但是要分场景。
答:一种是在ARC下会产生循环引用,而在MRC下不会产生循环引用,在ARC下我们可以通过断环的方式接触对应循环引用,但是有一个弊端如果这个blcok一直得不到调用,这个循环引用是没办法解除的。
问题3:怎样理解Block截获变量的特性?
对于基本数据类型局部变量是对其值进行截获。
对于对象类型局部变量是对其进行强引用(连同其所有权修饰符共同进行截获)。
对于静态局部变量对其指针进行截获。
对于全局变量或者静态全局变量是不产生截获的。
问题4:你都遇到过哪些循环引用?你是怎样解决的?
Block所引起的循环引用是两方面的。
一方面是block当中捕获的变量也是当前对象的成员变量,而这个block也是当前对象的成员变量,就会造成自循环引用,我们可以通过避免产生循环引用加__weak修饰符来避免这种循环引用
第二方面__block也会产生循环引用,一种是在ARC下会产生循环引用,而在MRC下不会产生循环引用,在ARC下我们可以通过断环的方式接触对应循环引用,但是有一个弊端如果这个blcok一直得不到调用,这个循环引用是没办法解除的。
问题5:block为啥可以修改全局变量而局部变量修改需要加__blcok
block可以修改全局变量,是因为全局变量放在推区,局部变量在栈区,所以不能修改,加上__block之后,相当于加了个标识位,遇到__block就把内存由栈区放在推区。