block其实也是一个对象,不过普通对象用来封装数据,或者实现某些功能。而block是对函数以及函数调用环境的封装。所谓的封装函数,是指将参数、返回值,函数体封装成一个函数。而且存储该函数的内存地址;所谓的封装函数调用环境,是指函数内部会捕获变量,并且存储这些被捕获的变量。
block的本质
__block本质是一个C++结构体
结构体里面有 :
isa指针,指向block所属的类
FuncFtr指针,指向该block对应的函数
block捕获的变量
copy函数,dispose函数。
block构造函数,用来创建并初始化一个block。
block的类型
全局block:没有使用外部普通局部变量的block就是全局block
栈block:使用了外部局部变量的block放在栈区。栈区的内存是被系统管理的,也就是说放到栈区的数据有随时被销毁的风险。
堆block:使用了copy修饰的block存在堆区。
- ARC下,系统会在某些情况下自动copy一份栈block到堆。
block赋值给一个强指针(__strong修饰的指针)
block作为函数的返回值
GCD里面的block,系统会自动复制到堆区
block捕获变量
block会捕获普通局部变量。
block内部会创建一个和外部变量名称一样的变量来接收这个局部变量。
- 普通局部变量,局部变量把值传递给block内部的变量
- 局部静态变量,局部变量会把指针传递给block内部变量
block不会捕获全局变量,直接使用使用全局变量。
block会捕获指针变量
- 只会捕获强指针变量,弱指针变量不会捕获。
__block修饰符 __block变量
因block内部创建一个变量接收外部局部变量,这就导致了修改的其实是block内部变量。使用__block修饰一下这个局部变量就可在内部修改了。
为什么被__ block修饰过的变量在内部可对其修改。
因为block捕获的不是 _block变量,而是 _block变量的地址,就类似于捕获静态变量一样.
__block修饰局部变量时,也会根据他修饰的是强指针还是弱指针来决定要不要持有该指针指向的对象。
__block的内存管理
系统吧栈block copy到堆时,也会把栈block内部变量也复制一份到堆区。并让堆区block持有它。
并让栈_block变量的的forwarding指针指向堆区的_block变量