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

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

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

友情链接更多精彩内容