Objective-C 循环引用

来源:互联网 发布:linux图形界面 编辑:程序博客网 时间:2024/05/18 00:09

前言

之前的博客内存管理中类与类的相互交叉引用使得我们手动管理内存并不是特别简单,在ARC下难道我们就一切都交给编译器吗,答案是否定在一些场景中开始需要我们(开发者)注意避免内存泄漏。今天来说说循环引用,在我们实际开发中是非常常见的,一不小心我们就调入坑里面了。

循环引用

循环引用:就是相当于两个人相爱,你中有我,我中有你,都各自放不下对方,即时分手也是相互想着对方。这个比喻不知道是否形象,就是这样的道理下面我们图片展示循环引用。

两个类A和B相互强引用对方,这样导致各自的retainCount +1 ,造成内存内存泄漏,那么我们如果有效的避免这种情况的发生呢?

如果我们把其中一个类不引用类就不会引起,这样就可以各自释放,但是在实际开发中这样情况还是比较常见的,我们引入weak(弱引用),这样我们使得两个相爱的人变为普通人。但是还是可以相互消息传递。如下图:

上图中只要有一个弱引用对象就不会引起循环应用,A中强引用B,B的retainCount +1,但是B弱引用A,A中的retainCount 并没有变化,所有如果A销毁那么对用retainCount -1 = 0 也就释放了。

那么在实际开发中我们在那么地方特别容易掉进这些坑里面,我们又该如何排查。

实际开发场景

场景一:类在使用delegate
这使我们在开发中最常见的问题,声明delegate,一定要使用weak;

场景二:block内代码快中
经常我们使用block内要使用本类的属性,那么这个时候要注意了,改用weak就用weak不要偷懒。block内部中用到的对象进行强引用(ARC)或者retainCount增1(非ARC)。在实际开发中分析注意。在之后的博客中我们来介绍block的内部实现和特性。

场景三:计时器NSTimer
这个涉及到计时器NSTimer的正确使用,我们创建定时传入target为self,

_timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(handleTimer:) userInfo:nil repeats:YES];- (void)cleanTimer {     [_timer invalidate];     _timer = nil; }

我们正确使用定时器,如果有外部类调用本类的定时器,那么对定时器的管理如停止应该交给使用类,如果直接在本类销毁,但是外部调用者计时器还在一直运行,就产生相互等待形成循环应用。

PS

实际开发中这个问题大家都知道但是还是难免会出现这样的问题,因为一个页面中引用很多的类和方法,在使用的时候难免疏忽,在排查过程中发现在内存泄漏,都要认真仔细的分析原因和相互持有关系到底是什么原因引起的,调试的时候是在找不到哪里可以使用逐行注释的方式进行排查,在dealloc内打断点查看是否销毁。以上内容如果有错误的地方欢饮大家留言,我会及时更正,谢谢!

1 0