在众多阅读类的APP中,比如:
这类比较稍微简单的界面中充斥着大量的的图片,多则6张,少则3-4张。再者像微博这类重型社交的APP,有的cell都已经有9张图片。图片的优化程度对整个界面的流畅度来说都是重中之重。(另外一个也很重要的地方就是文本的异步渲染),后几个系列也会说到。
像这种异步加载图片的开源库有很多:SD_WebImageView
YYWebImage Kingfisher
PINRemoteImage
…
开发者如果只是简单的调用一下 sd_setImageWithURL:
图片能够很好的显示出来。假如从网络加载的图片与自己设置的UIImageView的尺寸不一致,就会导致这种结果。
如果是真机调试 打开Instruments
中Core Animation
在右侧栏中打开
如果是模拟器,打开Debug ->Color Misaligned Images
这个选项检查了图片是否被缩放,以及像素是否对齐。被放缩的图片会被标记为黄色,像素不对齐则会标注为紫色。**黄色、紫色越多,性能越差。
解决办法:
1.与后台协商,让后台返回的图片尺寸与客户端UIImageView尺寸一致;
2.自己处理。
下面介绍下如何自己处理
1 | extension UIImage { |
很简单就是网络下载下来的图片按照自己设置的UIImageView的尺寸来重新draw一个。
1 | func setImage<T: UIImageView>(_ imageView: T, URLString: String, targetSize: CGSize){ |
重新给UIImageView设置image属性
重新打开Color Misaligned Images功能来检测一下
嗯! 不错哦,之前的黄色没有了。 本以为就达到了的要求。
但是用Instruments
中Time Profiler
来检测下处理该函数所需要的时间
用Core Animation来测下FPS
虽然已经很流畅了(注:文本用到了异步绘制), 基本在54左右, 但是距离满帧59 - 60还差那么一丢丢。
再来观察给UIImage扩展的这个方法 发现它是在主线程中执行,当快速滑动表格时,会有大量的图片在主线程中重新绘制。这个是造成缺失那几帧的主要原因。
解决办法:那就在子线程总去draw, 在主线程中去显示
1 | extension UIImageView { |
Objective-C
1 | -(void)drawImage:(UIImage *)image targetSize:(CGSize )size{ |
该方法也很简单,在子线程中去重新draw一个UIImage,在主线程中去显示。
调用:
1 | func setImage<T: UIImageView>(_ imageView: T, URLString: String, targetSize: CGSize){ |
重新测下帧数以及Time Profile
当快速滑动的时候基本上能够达到慢帧的状态
所用的时间也是非常少的。在16ms以内。