block循环引用问题--内存泄露
block中的循环问题
一. block容易引起引用循环的根本原因
原因一:
对于(block内部用到的)外部变量,对其执行retain 的时机 与该block的执行时机是不同步的- 在block声明的时候就对外部变量进行了retain
- 而block何时执行甚至是否执行都是不可预测的
原因二:
block 一般是匿名的,而且copy赋值的,手动释放block对象比较困难
注意
-
系统自带方法的block中访问外部变量,外部变量大部分不用__weak修饰,不存在循环引用问题
-
第三方框架中方法的block中访问外部变量,外部变量最好用__weak修饰,因为block可能被强引用,这时候如果被强引用的外部变量在block中使用会造成循环引用
-
使用IBOutlet修饰的变量,一旦失去所指向的对象,不会立刻被销毁,因为IBOutlet中有个强引用指向它,但当作用域结束就会被销毁
二. ARC和非ARC情况解决循环引用问题的方法
1. ARC
- 在ARC下,由于
__block
抓取的变量一样会被block retain,所以必须用弱引用才可以解决循环引用问题,iOS 5之后可以直接使用__weak
,之前则只能使用__unsafe_unretained
了,__unsafe_unretained
的缺点是指针释放后自己不会置空。
示例代码:
//iOS 5之前可以用__unsafe_unretained
//__unsafe_unretained typeof(self) weakSelf = self;
__weak typeof(self) weakSelf = self;
self.myBlock = ^(int paramInt)
{
//使用weakSelf访问self成员
[weakSelf anotherFunc];
};
1. 非ARC
- 在非ARC下,显然无法使用弱引用,这里就可以直接使用__block来修饰变量,它不会被Block所retain的
示例代码:
//非ARC
__block typeof(self) weakSelf = self;
self.myBlock = ^(int paramInt)
{
//使用weakSelf访问self成员
[weakSelf anotherFunc];
};