SDWebImage 源码学习笔记·前传 ☞ 升级 4.x.x
一、前言
前段时间对项目中使用的 SDWebImage 进行了一次升级 (3.7.6 → 4.4.2),发现变化比较大,本篇就记录一下升级过程中遇到的一些坑及填坑指南。
以此为契机,决定把之前阅读源码的笔记整理一下,于是就有了本系列后边几篇:
- SDWebImage 源码学习笔记·前传 ☞ 升级 4.x.x 后适配 WebP/GIF
- SDWebImage源码学习笔记 ☞ 结构及基本流程
- SDWebImage源码学习笔记 ☞ SDWebImageManager
- SDWebImage源码学习笔记 ☞ SDWebImageDownloader
- SDWebImage源码学习笔记 ☞ SDImageCache
二、升级
现在转回到本篇的主要内容,首先当然是升级了,不过最新版的 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 的开源库,所以需要使用 VPN。笔者使用了蓝灯 Lantern,然后发现 浏览器可以正常访问 Google 网站,可是命令行 pod install
依然会卡住,可以通过下边两条命令检测命令行是否已添加 VPN:
curl www.google.com
执行上述命令后,如果返回了网页信息,就说明 VPN 已经添加成功。
于是猛查资料,才有了下文:
-
下载 Lantern
-
安装后,打开 Lantern,页面如下,查询自己 VPN 软件 (Lantern) 的http代理:
可以看出 Lantern 的 http 代理运行在 52425(选中部分) 端口,不同机器上的端口号也会不同。
为什么说是 http 而不是 https 呢?将地址栏中的域名复制出来贴到任意文本编辑器,就会发现变成了 http://localhost:52425/axxx
3.在命令行输入以下指令,查看端口使用情况:
sudo lsof -i -P
查看端口使用情况.png
可以看出来基本使用的只有 2 个代理端口,52425 和 52427,结合第一步可以得出,52425 是 http 的代理端口,52427 是 https 的代理端口 😎
4.配置命令行代理端口,有两种方式:
A、给本地 git 设置 http/https 代理
// 添加 http/https 代理的指令 https://127.0.0.1:XXXX (XXXX代表端口号)
git config --global http.proxy https://127.0.0.1:52425
git config --global https.proxy https://127.0.0.1:52427
// 取消 http/https 代理的指令
git config --global --unset http.proxy
git config --global --unset https.proxy
// 这种方法可以 pod install 成功,不过 curl www.google.com 不成功,即打不出 Google 的网页信息。
B、设置系统全局变量 http/https 代理
切换到etc目录下 cd /etc
以管理员身份编辑 sudo vim bashrc
输入密码进入后, G $ 定位到文件末尾 按下键盘字母 i 开始输入,在最下面位置粘贴下面两句
export http_proxy=127.0.0.1:52425
export https_proxy=127.0.0.1:52427
然后退出保存 按Esc :wq
接下来让修改文件生效 source bashrc
最后一步 验证成功: curl www.google.com 如果收到 google 的 html 数据代表已通。
完成后 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 展示图片,不过和上边的第一种方案有以下不同:
- 使用
SDWebImageManager
的loadImageWithURL: 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];
本文完整示例代码见: HHSDWebImageStudy