SDWebImage与UIScrollView或UICollectionView一起使用多次收到“Received memory warning.”,最终程序闪退的原因分析和解决办法。
2016-05-12 22:58
831 查看
近期开发的项目中使用著名的SDWebImage(Github地址和项目介绍见底部传送门)与UIScrollView或UICollectionView结合实现cell图片的lazy loading。但是在不断下滑中遇到多次收到系统的“Received memory warning.”,最终程序闪退。闪退时Xcode显示与设备断开连接。
期间通过Xcode自带的instruments调试软件中的leaks功能检测内存使用量和泄漏情况(instruments具体介绍见底部传送门)。发现内存持续增加,直到persistent bytes达到600MB左右,程序崩溃,多次测试情况类似(iPhone 6 plus)。使用iPhone 6s plus,并没有闪退,persistent bytes最终达到800MB左右。此时考虑两代机型在运行时的空闲内存大小的区别,导致一个闪退,一个不闪退。
查询SDWebImage官方文档,介绍说SDWebImage会在收到“Received memory warning.”时自动释放内存内的图片缓存,而保留硬盘里的,如硬盘满了则会最终释放硬盘的图片缓存。而在显示图片时,它会优先查看内存里的缓存,是否有需要的图片,有就显示,没有就继续查看硬盘的图片缓存,如果都没有才去联网下载。最终再把下载的图片保存到内存或者硬盘。但是这与我们在leaks中观察到的内存持续增加是不相符的。
查询了网上各种类似问题,建议在- (void)didReceiveMemoryWarning;方法中加入
或者通过imageCache对象的maxMemoryCost或者maxCacheSize参数来设定cache的最大容量,依然无效。
最后通过代码的查找最终发现问题出在我们的某个参数对于SDWebImage下载的image进行了强引用,而导致SDWebImage在对缓存照片进行清理时,无法最终释放,依然停留在内存中。然后导致多次收到“Received memory warning.”,最终程序崩溃。
具体代码如下:
让我来看看LiveIndexData中userHeadImg的定义:
所以最终的原因就是userHeadImg的强引用,造成了SDWebImage管理的图片缓存无法正常释放。最终内存不断累加,导致内存满和程序崩溃。
感谢何建仁的大力帮助!
SDWebImage 传送门:
https://github.com/rs/SDWebImage
iOS测试软件instruments使用方法传送门:
https://www.raywenderlich.com/97886/instruments-tutorial-with-swift-getting-started
期间通过Xcode自带的instruments调试软件中的leaks功能检测内存使用量和泄漏情况(instruments具体介绍见底部传送门)。发现内存持续增加,直到persistent bytes达到600MB左右,程序崩溃,多次测试情况类似(iPhone 6 plus)。使用iPhone 6s plus,并没有闪退,persistent bytes最终达到800MB左右。此时考虑两代机型在运行时的空闲内存大小的区别,导致一个闪退,一个不闪退。
查询SDWebImage官方文档,介绍说SDWebImage会在收到“Received memory warning.”时自动释放内存内的图片缓存,而保留硬盘里的,如硬盘满了则会最终释放硬盘的图片缓存。而在显示图片时,它会优先查看内存里的缓存,是否有需要的图片,有就显示,没有就继续查看硬盘的图片缓存,如果都没有才去联网下载。最终再把下载的图片保存到内存或者硬盘。但是这与我们在leaks中观察到的内存持续增加是不相符的。
查询了网上各种类似问题,建议在- (void)didReceiveMemoryWarning;方法中加入
[SDWebImageManager.sharedManager.imageCache clearMemory]; [SDWebImageManager.sharedManager.imageCache clearDisk];来手动释放imageCache的内存缓存和硬盘缓存,依然无效。
或者通过imageCache对象的maxMemoryCost或者maxCacheSize参数来设定cache的最大容量,依然无效。
最后通过代码的查找最终发现问题出在我们的某个参数对于SDWebImage下载的image进行了强引用,而导致SDWebImage在对缓存照片进行清理时,无法最终释放,依然停留在内存中。然后导致多次收到“Received memory warning.”,最终程序崩溃。
具体代码如下:
-(void)setAttribute:(LiveIndexData*)data { if (data != nil) { // _pData = data; //设置背景图 [self.pHeadView sd_setImageWithURL:[NSURL URLWithString:data.iconUrlStr] placeholderImage:[UIImage imageNamed:@"broadcast_default"] options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { // 下方应该注释了,让用户照片全部交给SDWebImage来管理,由SDWebImage来在memory warning时,释放内存里的图片,否则_pData.userHeadImg的strong引用会影响内存里图片的释放。 // _pData.userHeadImg = image; }]; } }
让我来看看LiveIndexData中userHeadImg的定义:
@interface LiveIndexData : NSObject @property (nonatomic, strong) UIImage *userHeadImg; @end
所以最终的原因就是userHeadImg的强引用,造成了SDWebImage管理的图片缓存无法正常释放。最终内存不断累加,导致内存满和程序崩溃。
感谢何建仁的大力帮助!
SDWebImage 传送门:
https://github.com/rs/SDWebImage
iOS测试软件instruments使用方法传送门:
https://www.raywenderlich.com/97886/instruments-tutorial-with-swift-getting-started
相关文章推荐
- VC6.0打开文件以及向工程中添加文件时程序崩溃自动退出解决方法
- iOS开发中使用UIScrollView实现图片轮播和点击加载
- iOS开发之UIScrollView详解
- iOS开发中使用UIScrollView实现无限循环的图片浏览器
- 顶部可滚动小广告位 的封装 (UIScrollView+PageControl)
- ios7 中关于导航切换影响UIScrollView的问题
- 两个UIScrollVIew能够同步滚动
- UIScrollview要加载大量数据的时候,考虑到内存的消耗问题,我们不可能全部加载完。
- UIScrollview 无缝循环滚动实现
- 解决 IOS的UIScrollView的自动布局
- UICollectionView 代理方法
- CollectionViewCell 不执行 cellForItemAtIndexPath 方法的问
- UIScrollView无法滚动的问题
- cocos2d-x 一些有用的函数
- IOS UIscrollView 控件
- 关于NGUI中UITexture贴图自定义的shader文件在UISrollView中不报错的解决方案
- iOS collectionView实现瀑布流
- UICollectionview实现类似UITableview的sectionheader悬浮代码
- 缩放图片
- UIScrollView缩放