使用SDWebImage加载大量图片后造成内存泄露的解决办法
SDWebImage的知名度就不用说了,github上近10k的star,国内外太多的App使用其进行图片加载。
但是最近在使用过程中发现,在UITableView中不断加载更多的内容,使用SDWebImage会造成内存占用越来越大,导致memory warning最终terminate,稍微找了下问题原因,发现不少开发者都遇到过这个问题,中文的资料没有搜到该问题的解决办法,为了方便国内其他开发者遇到类似问题不浪费时间,这篇blog把解决方法记录如下:
首先检查了SDWebImage代码中对于memory warning的处理:
- (void)clearMemory { [self.memCache removeAllObjects]; }
其中self.memCache是NSCache类型的,可以看到SDWebImage本身对内存警告执行了操作,但是并没有什么X用。
用Instruments的allocations分析了一下内存使用情况:
可以看到内存基本都在decodedImageWithImage:这个方法里被占用了,查看了这个方法的内部实现,感觉还是比较正常的,只好求助google
最后在github上找到了这条issue:https://github.com/rs/SDWebImage/issues/538
下面回复很多(看来这个问题很多人都遇到了),甚至SDWebImage的作者本人rs也在下面进行了很多的回复(虽然他的回复并没有什么X用),回复里说到的问题原因和解决办法归纳如下:
1.rs本人回复的:SDWebImage用到的NSCache会在合适的时候(memory warning)释放内存,很多应用在加载大量图片的时候没有出现这种情况;
2.这个问题是因为SDWebImage对GIF的支持的代码造成的,去掉相关代码即可;
3.decodedImageWithImage的实现直接retrun image即可;
4.https://twitter.com/0xced/status/332252283758845953,这条Twitter也是蛮幽默的,通俗的翻译就是这条Twitter中描述的解决办法拯救了那些因为SDWebImage导致问题的程序员于水火之中。
挨个试了试上面4中解决方法:
第一种没什么可说的了,之前分析源码的时候就已经看到,也就是说rs的解决办法没用。
第二种办法,阅读源码可以发现SDWebImage中对GIF的处理只会针对GIF图片,并不会影响到png或者其他格式的图片,因此这个办法我觉得没用,没有尝试。
第三种,直接导致内存占用原因由CG raster data变成了ImageIO_PNG_Data,也是没用。
第四种,最开始我在receive memory warning的时候调用了这段代码
[[SDImageCache sharedImageCache] setValue:nil forKey:@"memCache"];
发现依然会出现问题,遂尝试了每次加载更多内容的时候都执行一次,终于内存不再持续增加了,也就是说第四种是最终的解决办法,在后续blog我可能会专门分析一下这个问题出现的原因和解决的原理。
总结如下:
在使用SDWebImage加载较多图片造成内存警告时,定期调用
[[SDImageCache sharedImageCache] setValue:nil forKey:@"memCache"];
可解决。