SDWebImage 源码学习笔记·前传 ☞ 升级 4.0 / 5.0 后适配 WebP/GIF

SDWebImage-源码学习笔记.png

2019.12.27 更新:最近发现 SDWebImage 升级到 5.0 以后加载 WebP 和 Gif 的方式也发生了改变,详见文末。

一、前言

前段时间对项目中使用的 SDWebImage 进行了一次升级 (3.7.6 → 4.4.2),升级过程中遇到了一些问题,于是又把源码读了一遍,为了记录读码过程,就有了这个系列:

本篇是第 1 篇,主要记述了升级过程中的遇到的问题及处理方案。

二、升级

现在转回到本篇的主要内容,首先当然是升级了,不过最新版的 SDWebImage 里边分了几个子 pod ,默认下载不全。为了满足我们的日常使用要求,还需要加上 WebP 和 GIF 这两个子 pod:

platform :ios, '7.0'

pod 'SDWebImage', '~> 4.0'
pod 'SDWebImage/WebP'
pod 'SDWebImage/GIF'

不过,在执行 pod install 的时候,发现 pod 'SDWebImage/WebP' 卡在了 Installing libwebp (0.6.0) 的地方。

据说 WebP 的解析库是 Google 的开源库,目前还无法直接使用,可以使用github上的镜像文件,这个网上很容易搜到,示例见文末参考。

完成后 pod 内部的结构如下:

SDWebImage4.0.png

三、使用

为叙述方便,此处将图片的 URL 定义成了宏:

#define URL_Normal          [NSURL URLWithString:@"此处是 普通静态图 地址"]
#define URL_WebP_Normal     [NSURL URLWithString:@"此处是 静态 WebP 地址"]
#define URL_WebP_Dynamic    [NSURL URLWithString:@"此处是 动态 WebP 地址"]
#define URL_GIF             [NSURL URLWithString:@"此处是 GIF 地址"]

第一种方案

  • png/jpg,直接使用 SDWebImage 提供的普通方法即可。
  • WebP,只要导入了 WebP 的子 pod,直接使用普通方法即可正常加载静态、动态的 WebP。
  • GIF,此处使用了 FLAnimatedImageView 代替 UIImageView 来展示 GIF。因为 SDWebImage4.0 以后,如果继续 直接 使用 UIImageView 将只展示 GIF 的第一帧,可以使用推荐的 FLAnimatedImageView 替换 UIImageView。
    // 普通静态图
    UIImageView *imgV = [[UIImageView alloc] initWithFrame:CGRectMake(125, 70, 160, 160)];
    imgV.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:imgV];
    [imgV sd_setImageWithURL:URL_Normal];

    // WebP
    UIImageView *imgVB = [[UIImageView alloc] initWithFrame:CGRectMake(125, 70+160+10, 160, 160)];
    imgVB.backgroundColor = [UIColor lightGrayColor];
    imgVB.contentMode = UIViewContentModeScaleAspectFill;
    [self.view addSubview:imgVB];
    // WebP 静态图
//    [imgVB sd_setImageWithURL:URL_WebP_Normal];
    // WebP 动态图
    [imgVB sd_setImageWithURL:URL_WebP_Dynamic];
    
    // GIF
    FLAnimatedImageView *imgView = [[FLAnimatedImageView alloc] initWithFrame:CGRectMake(125, 70+160+10+160+10, 160, 200)];
    imgView.backgroundColor = [UIColor lightGrayColor];
    imgView.contentMode = UIViewContentModeScaleAspectFill;
    [self.view addSubview:imgView];
    [imgView sd_setShowActivityIndicatorView:YES];
    [imgView sd_setImageWithURL:URL_GIF
             placeholderImage:[UIImage imageNamed:@"placeholder"]
                      options:1];

第二种方案

统一都使用 UIImageView 展示图片,不过和上边的第一种方案有以下不同:

  • 使用 SDWebImageManagerloadImageWithURL: options: progress: completed: 方法下载图片;
  • 根据得到的 data 判断图片类型: SDImageFormat format = [NSData sd_imageFormatForImageData:data];,基本原理是根据 data 的第一个字节来判断;
  • WebP 使用专用方法 sd_imageWithWebPData: 解码;
  • GIF 也使用专用方法 sd_animatedGIFWithData: 解码。
UIImageView *gifView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 70+160+10+160+10+200+10, kScreenW-20, 200)];
    gifView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:gifView];
    self.imgView = gifView;
    
    SDWebImageManager *mgr = [SDWebImageManager sharedManager];
    __weak typeof(self) weakSelf = self;
    [mgr loadImageWithURL:URL_GIF // URL_WebP_Dynamic // URL_WebP_Normal // URL_Normal
                  options:1
                 progress:nil
                completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL)
    {
        SDImageFormat format = [NSData sd_imageFormatForImageData:data];
        switch (format) {
            case SDImageFormatGIF:
                weakSelf.imgView.image = [UIImage sd_animatedGIFWithData:data];
                break;
            case SDImageFormatWebP:
                weakSelf.imgView.image = [UIImage sd_imageWithWebPData:data];
                break;
            case SDImageFormatPNG:
            case SDImageFormatJPEG:
                weakSelf.imgView.image = image;
                break;
            default:
                break;
        }
    }];

第三种方案

自定义 HHImageView,在它的 init 系列方法中添加了对 GIF 的解析:

[[SDWebImageCodersManager sharedInstance] addCoder:[SDWebImageGIFCoder sharedCoder]];

这种方案对最终的调用方来说,非常简洁,不需要对各种图片区别对待。

    HHImageView *customView = [[HHImageView alloc] initWithFrame:CGRectMake(125, 70, 160, 160)];
    customView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:customView];
    [customView sd_setShowActivityIndicatorView:YES];
    // 静态图
//    [customView sd_setImageWithURL:URL_Normal];
    // WebP 动图
//    [customView sd_setImageWithURL:URL_WebP_Normal];
    // WebP 静态图
//    [customView sd_setImageWithURL:URL_WebP_Dynamic];
    // GIF
    [customView sd_setImageWithURL:URL_GIF];

2019.12.27 更新:

  • 5.0 之后的版本中,默认添加了对 Gif 的支持,也就是说,需要移除 podfile 中的 pod 'SDWebImage/GIF'(不移除的话,pod install/update 会报错),然后直接使用加载 png/jpg 的方法就可以加载 Gif 图了,比如:
imageViewA.sd_setImage(with: URL(string: "http://hbimg.b0.upaiyun.com/43efd35d1e9cadc6d8ff5cdc5faccec06f1082bb4efc4-o8K27E_fw658"), completed: nil) // 皮卡丘揉脸的动画^_^
  • 对于 WebP,将之前的 subspec 抽出来,创建了一个单独的库 SDImageWebPCoder,使用时需要两步操作:
    • 在 podfile 文件中用下边的内容替换之前的 pod 'SDWebImage/GIF'
    pod 'SDImageWebPCoder'
    
    • 使用前,先给 SDImageCodersManager 添加一个 coder:WebPCoder,如下:
    let WebPCoder = SDImageWebPCoder.shared
    SDImageCodersManager.shared.addCoder(WebPCoder)
    

然后,就可以使用通用的方法加载 WebP 了,示例代码如下:

// 静态图
imageViewA.sd_setImage(with: URL(string: "https://www.gstatic.com/webp/gallery/2.webp"), completed: nil)
// 动图
imageViewB.sd_setImage(with: URL(string: "http://littlesvr.ca/apng/images/world-cup-2014-42.webp"), completed: nil) 

本文完整示例代码见: HHSDWebImageStudy

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    X先生_未知数的X阅读 15,937评论 3 118
  • 现在孩子的作业也越来越多元化了,不是我们以前写字算数那么简单了。不光要会写,还要会画会想象,有些题我们家长也不...
    XuZiHan阅读 153评论 0 0
  • 新教育人童喜喜说过:“人生中最最美好的事就是与美好的人相遇,一起做美好的事。”在你满怀热情对工作充满期待的时候,恰...
    空中云阅读 750评论 0 4
  • 我躺在草地上, 与草一同呼吸。 草轻轻问我:舒服吗? 我答:超柔软呢! 草说: 只有柔软的身躯才不会轻易被折断; ...
    Lily孙阅读 255评论 0 1
  • 今天下午在张校长的英明领导下,我校举行老师为同学们的饭后水果进行爱心捐款。为的是让孩子们能够营养搭配,健康成长。
    业余活动阅读 202评论 0 0