SDWebImage加载.gif 内存狂飙问题

于之前一直维护新浪博客,大量的东西都在这里,实在不想更换其他博客了,怎奈新浪对代码的排版,蛋疼至极,我尽量排版清晰些;

闲着没事,尝试用SD加载 .jif,在Cell里加载了大量的.jif,加载完成后意外出现了,内存狂飙到 700M+,滑动Cell会下降,大概到150M左右(所用的 .jif 本身比较大); 这个不能忍,于是各种解决:
在测试过程中发现SD 对混合图层的处理也不是很到位;不管是动态图还是静态图,都未做混合图层处理;

顺便提一下混合图层:
Color Copied Images:该选项可以给绘制时被Core Animation复制的图片添加蓝绿色叠加层
Color Misaligned Images:如果图片边界没有与目标像素完美对齐,该功能可为图片叠加上一层品红色。如果图
片使用确定的比例大小绘制,那么该功能会为图片添加一层黄色叠加。

原因概述: SD在对 .jif 的处理过程中采用了一个数组存储 jif 的帧图片,然而并没有及时释放;注意文中标注”
“的地方;
解决方案: 1. 采用YY_WebImage框架,
2. 在使用SDWebImage加载较多图片造成内存警告时,定期调用 [[SDImageCache sharedImageCache] setValue:nil forKey:@"memCache"]; 比如tableView加载更多的时候;

这里只介绍方案二:

1.首先分析SD加载 jif 的过程:
sd_animatedGIFNamed是SDWebImage提供的加载gif图片的一种方法。我们点进去这个方法去看以下。

sd_animatedGIFNamed 这个方法的实现如下。生成一个UIImage对象。

  • (UIImage *)sd_animatedGIFNamed:(NSString *)name {
    //取到屏幕分辨率
    CGFloat scale = [UIScreen mainScreen].scale;
    //是否是高清屏
    if (scale > 1.0f) {
    //如果是高清屏 取@2x图片 读取图片
    NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name
    stringByAppendingString:@"@2x"] ofType:@"gif"];
    //图片转换为
    data NSData *data = [NSData dataWithContentsOfFile:retinaPath];
    //如果图片存在
    if (data) {
    //调用sd_animatedGIFWithData 生成image实例
    return [UIImage sd_animatedGIFWithData:data]; }
    //如果@2x图片不存在 读取普通图片
    NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];
    //图片转换为
    data data = [NSData dataWithContentsOfFile:path];
    //如果图片存在
    if (data) {
    //调用sd_animatedGIFWithData 生成image实例
    return [UIImage sd_animatedGIFWithData:data]; }
    //如果图片不存在
    return [UIImage imageNamed:name]; }
    else { //如果不是高清屏 读取普通图片
    NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; //图片转换为data
    NSData *data = [NSData dataWithContentsOfFile:path];
    //如果图片存在
    if (data) {
    //调用sd_animatedGIFWithData 生成image实例
    return [UIImage sd_animatedGIFWithData:data]; }
    //如果图片不存在
    return [UIImage imageNamed:name]; } }

注释已经很详细了,这个类方法里面主要是确定当前设备的分辨率,以便加载不同分辨率的图片。
然后通过sd_animatedGIFWithData 后续处理
2.再来看看sd_animatedGIFWithData:

  • (UIImage *)sd_animatedGIFWithData:(NSData *)data {
    if (!data) {
    return nil; }
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    size_t count = CGImageSourceGetCount(source);
    UIImage *animatedImage;
    if (count <= 1) {
    animatedImage = [[UIImage alloc] initWithData:data];}
    else {
    // 注意这里的数组:
    NSMutableArray *images = [NSMutableArray array];
    NSTimeInterval duration = 0.0f;
    for (size_t i = 0; i < count; i++) {
    CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
    duration += [self frameDurationAtIndex:i source:source];
    // 数组不断的添加帧图片,然而并没有及时释放
    [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
    CGImageRelease(image); }
    if (!duration) {
    duration = (1.0f / 10.0f) * count; }
    animatedImage = [UIImage animatedImageWithImages:images duration:duration]; }
    CFRelease(source); return animatedImage; }
    先看这行代码
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    CGImageSourceRef定义如下,
      typedef struct CGImageSource *CGImageSourceRef;
    可以看到它是一个CGImageSource 指针。
    CGImageSource是个什么东东呢?
    CGImageSource是对图像数据读取任务的抽象,通过它可以获得图像对象、缩略图、图像的属性(包括Exif信息)。
    那么这行代码可以这样理解:通过nadata取到图像的以系列信息。
    再看size_t count = CGImageSourceGetCount(source);
    这行代码是读取CGImageSourceRef有几个图片对象。
    下面就不难理解了,
    CGImageSourceCreateImageAtIndex :从source里面读取各个图片放入数组里面。
    读取显示图片的 时间:
    duration += [self frameDurationAtIndex:i source:source];
    计算图片显示时间:
  • (float)frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source { float frameDuration = 0.1f;
    CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
    NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
    NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
    NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
    if (delayTimeUnclampedProp) {
    frameDuration = [delayTimeUnclampedProp floatValue]; }
    else {
    NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
    if (delayTimeProp) {
    frameDuration = [delayTimeProp floatValue]; } }
    if (frameDuration < 0.011f) {
    frameDuration = 0.100f; }
    CFRelease(cfFrameProperties); return frameDuration;
    }
    最后:
    从数组中读取帧图片并显示:
    animatedImage = [UIImage animatedImageWithImages:images duration:duration];
    播放数组里里面的图片。
    从以上分析中可以知道: SD在处理 jif 的时候 采用数组暂存了 jif 的帧图片,并未及时释放,最终导致内存飙升问题;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容