将近一个月没有写文章了,借口就不一一罗列了。。。。
废话不多说,进入正题。
谈到循环引用这个问题,相信很多iOS的童鞋至少都在运用block技术的时候遇到过,同样的,很多童鞋肯定也是通过weak这个关键字来处理的,但是我相信,这其中肯定有不少童鞋并没有搞明白为什么会发生循环引用。本篇短文章,就以自己的理解与总结,浅谈一下OC中的循环引用。
首先,来看一下什么是循环引用。这里,以一个小例子来简述:
有两个类:Man与Woman,Man中有一个Woman属性,而Woman中又有一个Man属性,专业简洁一点的说法,也就是Man与Woman相互引用,此时,咱们在控制器的viewDidLoad方法中创建Man对象man与Woman对象woman,然后再执行这两个对象的release方法,此时,对于viewDidLoad方法来说,已经释放了自己对于man和woman这两个对象的持有权,但是,此时man与woman的引用计数不是0,而是1,因为它们互相引用了。这就从而导致man与woman这两个对象永远无法释放,从而就造成了内存泄露的现象。
上面这个简单的小例子,就是循环引用的呈现,可能对于有些只在block中遇到循环引用问题的童鞋来说,还理解不了:难道block中的循环引用就是因为这个????
下面,咱们就来总结一下,循环引用这个现象会在哪些情形下出现。
一、运用NSTimer时。
(可能很多童鞋都跟我一样,接触NSTimer要比接触block早一点点。)
运用NSTimer时,必然少不了target这个概念(通常情况下,这个target就是self),而NSTimer默认会对target有强引用,因此,如果在target(self)释放之前,没有先释放或者停止NSTimer,那么就会出现循环引用引起的内存泄漏问题了。
归结于上述原因,因此,在使用NSTimer时,咱们总是在target(self)释放之前,先调用NSTimer的invalidate方法来停止NSTimer(更保险的做法是,在target的dealloc方法中置空NSTimer),如果存在NSTimer的相关运行受外界控制的情形时,则应该向外界提供停止NSTimer的方法,让外界在释放target之前,先停止NSTimer。
二、运用block时。
(终于该说block了。。。。)
当block作为属性变量存在于一个类中时,并且这个类在block的实现代码中使用了这个类自身(self),那么就会出现循环引用的现象。对于这种情形,咱们的处理方法就是像本文开头提到的那样,在block块里面,对这个类进行弱引用(weakSelf)。
三、运用delegate时。
很多童鞋都用过delegate与protocol,那么为什么delegate要用weak这个关键字来修饰呢?咱们用UITableview来简单说一下。
tableview的显示,肯定离不开控制器Controller,因为Controller已经对tableview有一层强引用,此时如果再将delegate设置为strong,那就说明tableview又强引用着Controller(因为Controller是tableview的delegate),这样,就必然存在循环引用了。
因此,在使用protocol及delegate时,通常都是将delegate设置为weak弱引用(MRC下则必须是assign)。
以上,就是对循环引用的一些总结,都是楼主在日常工作中的一些认识,或许存在肤浅、甚至错误的地方,欢迎各位读者的各种评论。
PS:博客园中的iOS开发者是不是很少?怎么感觉都是java与.net的天下。。。。