iOS首页渲染优化 -- imageName:

 

前言web

随着APP功能的逐渐强大和业务上的逐渐完善,目前对于iOS开发者来讲,对于APP的优化逐渐显得尤其重要,本篇基于APP渲染优化上探讨一下imageName:的爱恨情仇,下面以UITabBarItem渲染图片为例,一步步以实践的方式进行分析。缓存

分析异步

首先看下未优化前的效果图:async

测试设备:iPhone7 ,系统:12.1函数

1.gif

细心的同窗应该可以发现,在登陆进入首页,到首页渲染结束,中间会有一段白屏,为何会白屏一会而没有立刻渲染首页呢,第一感受确定是这中间造成主线程阻塞了,让UI没有当即渲染出来,其实事实上确实是这样,那接下来咱们经过Instruments分析一下哪里执行了耗时操做以致于首页渲染被阻塞了。Instruments里面有个工具TimeProfiler,能够用来帮咱们查看哪里有耗时操做。关于这个工具的使用和配置网上不少介绍本篇不作重点分析了,我直接粘调试的图片了。工具

2.webp.jpg

经过TimeProfiler的结果一目了然,在CustomTabBarItem里面作了什么用了387ms。能够在工具里面直接右键进入到到这段耗时代码的位置。我总共测试了五个tabbar渲染item图片的耗时:测试

3.webp.jpg

4.webp.jpg

看打点日志就很恐怖了,执行两个imageName:就消耗了主线程差很少100ms的时间,五个tabbar那就是500ms的时间,显然这就是上面效果图出现白屏的缘由了,实际上imageName:是会对图片进行解码以后再渲染的。优化

既然缘由找到了,那就尝试解决一下。将这个耗时的操做放到子线程执行,这里也是参考了SDWebImage的图片编解码的思路,SD在拿到图片data的时候并无将它直接转为image对象,而是在子线程里面作了一个解码的操做,这样已经被解码的图片就赋值给imageView的时候就不会再进行解码,也就不会妨碍主线程了。ui

- (void)decodedImageWithImageName:(NSString *)imageName block:(void(^)(UIImage *image))block {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        @autoreleasepool{
            UIImage *image = [[UIImage imageNamed:imageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
            image = [UIImage decodedImageWithImage:image];
            dispatch_async(dispatch_get_main_queue(), ^{
                if(block)
                block(image);
            });
        }
    });
}

 

代码实现很简单,就是将图片的操做放入到一个全局队列中,固然也能够本身建立一个队列去执行这个异步操做。decodedImageWithImage:为SD的代码,须要#import "SDWebImageDecoder.h",具体实现网上对这一块的源码解释的比较多,很容易理解。spa

这样咱们的图片通过这层处理以后,咱们再来看一下优化以后的效果:

5.webp.jpg从总计500ms降到了6ms,基本能够忽略不及了,咱们再在真机上面看一下优化后的效果:

6.gif

通过同事的提醒和评论区小伙伴的质疑,我又从新测试了一下imageName:的加载耗时,获得一种现象,若是将图片资源放入在文件目录中,每张图片第一次加载依旧耗时大概30ms左右,由于imageName:方法对图片有缓存,因此测试屡次加载须要多张不一样的图片进行测试。另外我将测试图片放入Assets.xcassets中每张图片加载耗时大概在1ms左右,猜想Assets.xcassets提早将图片作了缓存。

测试图片:

7.webp.jpg

总结

经过上面的分析,实际上imageName:这样的UI函数咱们每天都在用,可是从没想过它在某些地方能产生这么大的影响。问题的定位和解决其实都很简单,可是这种简单的问题每每会被咱们开发者忽略掉,产生一些很差的结果,值得反思。

相关文章
相关标签/搜索