block是什么:
- 是一种匿名函数,没有函数名,只有函数体
- 是一种数据类型
是一个代码块,在需要的时候执行
block所在的内存区域
NSGlobalBlock:类似函数,位于全局区(不在堆栈中)
- NSStackBlock(存在于 MRC 环境下):位于栈内存,函数返回后Block将无效;
NSMallocBlock:位于堆内存
block 的内存管理
- 不引用任何外部变量的 block(NSGlobalBlock),存储在全局区
- 引用了外部的局部变量,block便会被压入调用它的函数的栈中(NSStackBlock),存储在栈区,此时有其它函数调动 block 会出现野指针错误,可以通过 copy,将 block 存储到堆区(转变成NSMallocBlock),来解决野指针错误
- 在 ARC 下,block默认分配到堆区(NSMallocBlock)
- 对 NSStackBlock 进行 copy 操作就会得到 NSMallocBlock,但是 retain 操作不会得到
block 对基本数据类型的引用
- 如果是局部变量:两次输出的结果都为0
- 如果是全局或者静态变量:输出的结果为 0 ,10
- 对于基本数据类型的局部变量,当 block 对其引用时,会创建该变量的一份快照,再次修改变量的值是不会改变快照的值,所以 block 内部不能直接修改外部局部变量的值;如果要修改需要用 __block 修饰变量;
- 对于基本数据类型的全局和静态变量,block 对其引用,不会创建快照而是直接引用
__block 修饰的局部变量等效于全局或者静态变量
block的循环引用
循环引用常出现在 block 内部使用 self ,为了解决这个问题,一般在 block 内部出现 self 就将 self 转变为弱引用(__weak typeof(self) weekself = self)