iOS 中内存泄露 - Block就会循环依赖?
Hi,
本文主讲,Block中使用self,为何会循环依赖。
最近公司对代码质量很在意,这是好事。
我们使用Coverityz做了检测,的确有一大堆的问题。
So tm what!
我呢,研究各种case下的问题,以及解决方案。
Now,轮到了内存泄露的case,先来搞这个Block导致的内存泄露,内存常驻吧。反正tm的都是内存浪费。
先来了解下,啥是内存吧,为何泄露?
我简单搜了一下,查看了该猿友的文章http://www.cnblogs.com/houjun/p/4909413.html。
通俗点,有的区域(栈)的土地是有人管理的,会进行回收等自动处理,好比说该区域属于国家,你挂了,土地就回收了;有的区域(堆),是公共的,谁都可以用,也没人管理,你只享用某一块空间,却不管清理该空间的废物垃圾,等你挂了,就会影响该空间的再次使用。
当然这也是计算机系统的机制问题,在某些case下某空间无人占领,就该清除,当然也不保证你私藏的电影会不会被清除。
回到主题,为啥内存浪费,该有点头绪了吧,就是没人处理呗。
经常会有人讲,block中使用self会产生循环引用。
他告诉你了规则,那为何产生循环应用?循环引用又咋了?
在下才疏学浅,也是通过查看其他猿友的文章。
http://www.cnblogs.com/biosli/archive/2013/05/29/iOS_Objective-C_Block.html
http://www.cnblogs.com/flyFreeZn/p/4264220.html
我们会想,对象都分配到栈中,就有人管理了,不会有内存泄露的问题了,寡人只想告诉你,有想法是好的,还得按规矩来,哪种case下的对象,在哪里分配空间,是系统决定的。
通过其他猿友的,总结就是ARC下,就是以下两条准则来理解为啥循环依赖、为啥内存常驻了,
声明一个block对象,它是在栈中的;如果Block作为属性property,默认是strong修饰的,我们也会用copy来修饰,两种修饰,都会将Block对象 copy到堆(无人管地带)上。
那么常见问题来了,结合iOS的内存管理机制(引用计数),思路也就有了。
1、临时定义的block,不是copy、strong出来的,如果使用self,不会循环依赖。
为啥咧?因为block中的任务结束(走完{...}),他也就会被处理干净了,相关变量,也会清除,最主要,它在栈中,不信你试试。
当然某些case下,会延迟释放self,比如某个UIViewController的对象中,你在dissmiss页面前,使用performAfter 、dispatch_after来提交了一个任务块(block),里面使用了self,就会延迟释放self,看个人意愿吧,我一般在这种case下,都使用weak,来减少不必要的任务处理。
2、属性block对象中,使用self,会循环依赖,导致self不自动释放,导致内存浪费
为啥咧?因为block此时在堆中,对象self和对象block相互持有对方,导致彼此至少引用计数都是1,tm的谁也没法释放,此时最想说,真是不怕神一样的对手,就怕猪一样的队友。