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函數咱們每天都在用,可是從沒想過它在某些地方能產生這麼大的影響。問題的定位和解決其實都很簡單,可是這種簡單的問題每每會被咱們開發者忽略掉,產生一些很差的結果,值得反思。

相關文章
相關標籤/搜索