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];
};
原文地址:https://www.cnblogs.com/KrystalNa/p/4803800.html