很早之前,我们的项目中就已经采用了webp格式,但是由于webView本身并不能解析webp格式,所以我们基于webView的文章详情页就无法使用到这项优化。
那么有没有什么办法能实现呢?当然是有的。
在开始技术讲解之前需要先说明,本文的技术方案,是基于本项目的情况:文章的正文大部分通过接口直接获取到,通过在客户端本地进行html正文组装,最后通过webView的loadHTMLString方法进行加载显示。普通的图片可以通过转换链接得到webp服务器获取到相应的webp版的图片。
本项目中,图片缓存使用了SDWebImage,并且开启了webp支持功能,那么我们对详情页webView的处理也会基于此来实现。
通过思考,方案其实还是比较明确的,就是替换html中图片链接,通过客户端下载webp图片,然后在通过js刷新出页面上的下完的图片,但实际开发中也遇到了一些坑,比如:
- HTML解析库的setAttributeNamed不能增加属性
- webp服务器图片下载后的默认缓存时gif不能正常存储
- 下载完的图片不能实时通过js更改src为本地文件地址加载出来
最终的技术实现:
1.对下载回来的html内容进行处理,获取所有图片链接,并进行webp链接处理转换
对html内容的解析处理我使用的是Objective-C-HMTL-Parser,但是该库已经多年不维护,这里有我fork后进行部分优化调整的版本:https://github.com/YueRuo/Objective-C-HMTL-Parser
处理html图片核心处理逻辑代码:
@try {
HTMLParser *parser = [[HTMLParser alloc] initWithString:htmlContent error:&error];
HTMLNode *bodyNode = [parser body];
if (error) {
return;
}
//得到所有的img标签
NSArray *inputNodes = [bodyNode findChildTags:@"img"];
for (HTMLNode *inputNode in inputNodes) {
NSString *imageSrc = [inputNode getAttributeNamed:@"src"];
if (!imageSrc) {
continue;
}
NSString *newSrc = [[GlobalVariable shareInstance] resizeWebpImageWithUrl:imageSrc size:CGSizeMake((SCREEN_WIDTH - 20) * 2,