解决iOS开发中涉及到的retain cycle导致控制器无法释放的问题

来源:互联网 发布:苹果电脑安装淘宝助理 编辑:程序博客网 时间:2024/06/08 00:38

这几天碰到项目中一个bug,从一个列表进入任务详情页面,回复一条信息后,会导致列表中所有的cell点击进去全都是刚刚回复的那条任务详情。bug不细说,因为同事之前改过一个问题,有一个对列表数据赋值的操作,但是这个操作只会在接口调用完成后在详情控制器里进行,如果退出了,那么控制器销毁后就不会赋值,也就没有后来的bug。因此我检测了内存,调试了控制器的dealloc方法,果然,控制器没有被释放,应该是存在一些retaincycle导致的。

这个问题困扰了我三天,因为这个控制器有4个内嵌控制器,主控制器不能释放,4个内嵌控制器也不能释放,如果有几个retain环的话,那我碰巧改过一个之后,也解决不了问题,为了不引入新bug,只能改回去,这样就无解了。所以解决了一个之后必须记录下来,有思路。

这里比较重要的是,在arc下要打印出关注的控制器的retaincount。这里用到一个方法-

NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)theVC));

在跳转过来的控制器中,用weak方式持有一个关注的控制器,就可以在这个关注的控制器被pop的时候打印他的值了。

这样,每次解决一个潜在问题之后,就可以看到retaincount减少了。我首先把控制器中所有可能有问题的代码全部注释掉,然后看retaincount。看一下当dealloc可以执行时,这个retaincount的值是多少。然后,再去关注的控制器里面,分部分的注释代码,直到注释了一小部分代码之后,这个控制器的dealloc就可以被执行了,然后逐步缩小范围。缩小到最后,差不多都是strong代理,block循环引用(self.request标记了接口调用),以及一些cell用strong引用所在控制器的问题。还有一个是关联对象问题,在封装sdwebimage的时候,关联对象强引用了所在控制器。这样,分别调试了五个控制器,最终解决了retaincycle引起的内存泄露问题。

因为retain cycle引起的内存泄露现象不明显,只有在引起bug的时候可能才引起重视。所以,最终积累多了,很难调试。我前两天的工作进度很慢,因为没有调试思路。今天确定这个思路之后,用控制变量法迅速找到了这几处问题并解决。因为这个比较底层,顺带解决了几个其他位置的bug,也增加了稳定性,降低了因内存问题崩溃的几率。其实在开发的时候,每个控制器下面都加上dealloc方法并打上断点,可以预防这种问题。

0 0
原创粉丝点击