常见的出现内存循环引用的场景有哪些?

  • 定时器(NSTimer)

NSTimer经常被作为某个类的成员变量

@property(nonatomic,strong)NSTimer *timer;

而NSTimer一般都要指定self为target,容易造成循环引用,self->timer ->self

self.timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timer) userInfo:nil repeats:YES];

另外,若timer一直处于validate状态,则其引用计数器始终大于0,因此在不再使用定时器以后,应该先调用invalidate方法, 说白了就是一定要移除定时器

  • block的使用

block在引用外部的变量是,会对外部变量进行copy操作。在(ARC)模式下会对变量进行强引用,(MRC)模式下变量retainCount加1。当一个类把block作为成员变量时,在block内部使用了这个类本身。造成self-->block-->self或者self-->block-->类的成员变量循环引用的情况。

解决办法:在给block赋值时在外部用

ARC:
__weak mySelf = self;

MRC:
__block mySelf = self;

用__block修饰使用到的类。

  • 代理 delegate:

把代理设置成strong,执行语句(self代表控制器)后,

UIScrollView *scrollView = [UIScrollView alloc] init];
scrollView.delegate = self;

当控制器想要销毁时,控制器被一个强指针指着,而scrollView添加到控制器view中也被强指针指着,也无法销毁,那么它的delegate不会销毁。delegate指向控制器。造成了循环引用。把delegate变成weak:当控制器生命周期结束时,view随之销毁,内部子空间也随之销毁,delegate也就销毁了。规避该问题的杀手锏就是声明 delegate 的时候使用 assign[MRC]或者 weak[ARC].

你可能感兴趣的:(常见的出现内存循环引用的场景有哪些?)