Block

  • Block介绍
  • 截获变量
  • __block修饰符
  • Block的内存管理
  • Block的循环引用

一、Block介绍

1.什么是Block

  • Block是将函数及其执行上下文封装起来的对象

写法:


image

2、Block 的调用

  • Block的调用就是函数的调用

二、截获变量

问题:这个结果为什么是12
image

1.变量的分类

  • 局部变量(基本数据类型、对象类型)
  • 静态局部变量
  • 全局变量
  • 静态全局变量

2.针对不同变量的截获

  • 基本数据类型的局部变量截获其值
  • 对象类型的局部变量连同所有权修饰符一起截获
  • 指针形式截获局部静态变量
  • 不截获全局变量、静态全局变量
image

三、__block 修饰符

什么情况下使用:

  • 一般情况下,对被截获变量进行赋值操作需要添加 __block 修饰符(赋值 不是 使用)
image

(需要)

image

(不需要)

对变量进行赋值时:

  • 局部变量(基本数据类型、对象类型),都需要 __block 修饰
  • 静态局部变量、全局变量、静态全局变量不需要__block 修饰
__block 修饰的的变量变换成了对象
image

四、Block 的内存管理

Block的类型:

  • 全局的 -- _NSConcreteGlobalBlock
  • 栈上的 -- _NSConcreteStackBlock
  • 堆上的 -- _NSConcreteMallocBlock

不同类型 Block 的位置:


image

Block 的 Copy 操作

image

1.栈上 Block 的销毁

image

2.栈上 Block 的 Copy (栈上的 Block释放时,MRC 下会引起内存泄漏,因为堆上的 Block 不会进行销毁)

image

3.栈上 __block 的变量 Copy

image

3. __forwarding 存在的意义

  • 不论在任何内存位置,都可以顺利的访问同一个__block 变量。

五、Block 的循环引用

例1:

问题:


image

解决方案:


image
原理:对对象类型的局部变量连同所有权修饰符一起截获,而数组一般是用 strong 修饰,所以会引起循环引用,而改成 __weak 之后,为弱引用,所以不会引起循环引用

例2:

问题:


image

答案:

  • MRC下,不会产生循环引用
  • ARC下,会产生循环引用,引起内存泄漏

分析,ARC 下:


image

解决方案:


image

缺陷:
若 Block 一直未被调用,则循环引用会一直存在

六、总结

  • 什么是 Block?
  • 为什么 Block 会产生循环引用?(如果当前 Block 对当前对象进行截获,则会对当前对象有强引用,又当前对象强引用 Block ,所有会产生自循环引用,可用 __block 修饰截获变量解决;;__block 修饰在 ARC 下循环引用,方法见上文)
  • 怎样理解 Block 截获变量的特性?
  • 你都遇到过哪些循环引用?你是怎样解决的?

你可能感兴趣的:(Block)