你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> iOS實錄17:網絡圖片的優化顯示

iOS實錄17:網絡圖片的優化顯示

編輯:IOS開發基礎

原文

導語:App中顯示的圖片大部分來自服務器,一般使用SDWebImage幫我們下載並顯示,但是這並不是最好的效果,本文介紹如何優化網絡圖片的顯示。

一、概述

1、SDWebImage庫概述

  • 在SDWebImage庫中,SDWebImageManager是管理器,持有SDWebImageDownloader和SDImageCache單例,負責調度圖片的異步下載、緩存和獲取。

  • SDWebImageDownloader是下載器,負責異步圖片下載任務的調度,下載器中維持了一個圖片下載隊列,隊列中管理若干SDWebImageDownloaderOperation下載任務;該任務繼承自NSOperation,封裝了圖片的下載任務,支持並發操作。圖片下載的網絡請求和響應是由NSURLSession類負責管理的。SDImageCache是緩存器,負責下載圖片的緩存和讀取。

  • 總之,SDWebImage庫提供了一整套的網絡圖片異步下載和緩存機制,還增加了UIImageView、UIButton等的Category,方便顯示網絡圖片。

2、存在的問題

  • 由於網絡圖片一般不會有@2x和@3x之分,通過SDWebImage庫下載的圖片不加以處理就直接顯示,會有一些常見的問題,如像素不對齊。

  • App中經常使用圓角圖片,一般采用裁剪圖片的方式;但是這些圖片源來自服務器(本地圓角圖片讓UI直接提供就可以了),我們需要在SDWebImage基礎上增加對網絡圓角圖片的處理。

二、常見圖片顯示問題

主要有三類:像素不對齊、像素混合 和圓角處理

1、像素不對齊

  • 像素不對齊是指物理像素(pixel)不對齊;出現像素不對齊,會導致GPU在渲染時,對沒對齊的邊緣,進行插值計算,造成性能損耗了。

  • 當圖片的size和顯示圖片View的size不同 或 圖片的scale和屏幕的scale不同,就會發生像素不對齊的問題。要想像素對齊,必須保證image.size和顯示圖片view.size相等 且 image.scale和 [UIScreen mainScreen].scale相等。

  • iPhone模擬器中的Debug -> Color Misaligned Images選項 或Core Animation->Display Settings->Color Misaligned Images選項都可以將像素不對齊的部分顯示出來。

  • 當UIView(及其子類)的frame像素不對齊顯示洋紅色;當圖片的像素大小與控件的大小不一致,顯示黃色。

    說明:了解更多請參考iOS優化錄1:解決iOS中像素不對齊問題

2、像素混合

  • 像素混合是指在某視圖為透明背景色,GPU在渲染視圖時,需要將該視圖和下層視圖混合(Blend)後才能計算出該像素點的實際顏色;這增加了GPU的工作,損耗了性能。

  • 當圖片是透明圖片時,像素混合必然會發生。所以顯示的圖片最好是不透明的。

  • iPhone模擬器中的Debug ->Color Blended Layers選項 和 Core Animation ->Display Settings ->Color Blended Layers都可以將像素混合的部分顯示出來。

  • 發生了像素混合的區域顯示紅色,正常則顯示綠色。

    說明:之前對像素混合的關注比較少,而像素混合對性能的影響有多大,還需要後續工作中去驗證;但是可以避免像素混合就盡量避免。

3、圓角圖片的問題

  • 不建議的方案1:通過設置cornerRadius值和masksToBounds=YES實現圓角效果。因為它會觸發GPU的離屏渲染,引起性能問題。模擬器中的Color Offscreen-Rendered可以檢測是否發生離屏渲染(如果出現黃色就發生了離屏渲染)。

  • 不建議的方案2:通過設置view.layer的mask屬性,將另一個layer蓋在view上,也可以實現圓角的效果,但是同樣會觸發離屏渲染,引起性能問題。

  • 可參考的方案:在需要添加圓角的視圖上再疊加一個部分透明的視圖,只對圓角部分進行遮擋。雖然不會有離屏渲染和額外的GPU計算,但是不靈活,使用范圍有限。

  • 建議的方案:使用Core Graphics重新繪制帶圓角的圖片,雖然在顯示上提升了性能,但是增加了繪制的工作,所以要做好異步繪制和緩存工作,盡可能避免重復繪制。

說明:離屏渲染是圖片圓角處理中討論比較多的問題,利用Core Graphics繪制是個比較主流的選擇。

三、QSImageProcess方案

QSImageProcess方案是我定制的圖片處理方案,為了適應對本地圖片以及網絡圖片的處理,做了一些優化工作。

1、核心類:QSImageProcess

可以同步或異步處理圖片,接口定義如下:

typedef void(^QSImageProcessCompletedBlock)(UIImage *outputImage);

@class QSImageProcessConfig;

@interface QSImageProcess : NSObject

/**
 圖片處理配置對象
 */
@property (nonatomic,strong)QSImageProcessConfig *config;

+ (nonnull instancetype)sharedInstance;

/**
 異步圖片處理
 @param image 待處理的圖片
 @param config 圖片處理配置對象
 @param completedBlock 處理完成塊
 */
- (void)processImage:(UIImage *)image
              config:(QSImageProcessConfig *)config
           completed:(QSImageProcessCompletedBlock)completedBlock;

/**
 同步圖片處理
 @param image 待處理的圖片
 @param config 圖片處理配置對象
 @return 返回處理好的圖片
 */
- (UIImage *)processImage:(UIImage *)image
                   config:(QSImageProcessConfig *)config;


@end

說明:圖片的處理是耗時操作,在異步處理中,將該任務應交給GCD並發隊列,通過QSDispatchQueue控制並發隊列的最大並發數

2、UIImageView的QSImageProcess分類

@interface UIImageView (QSImageProcess)

/**
 加載並顯示網絡圖片,調用前需要先設置好UIImageView的frame或bounds
 @param url 圖片url
 @param placeholder 圖片處理配置對象
 */
- (void)qs_setImageWithURL:(nullable NSURL *)url
          placeholderImage:(nullable UIImage *)placeholder;

/**
  加載並顯示網絡圖片
 @param url 圖片url
 @param placeholder 占位圖
 @param config 圖片處理配置對象
 */
- (void)qs_setImageWithURL:(nullable NSURL *)url
          placeholderImage:(nullable UIImage *)placeholder
                    config:(QSImageProcessConfig *)config;
@end

說明1:接口1不需要設置QSImageProcessConfig對象,采用默認的方式,根據UIImageView的size來輸出顯示不發生 像素混合和像素不對齊的圖片。

說明2:接口2使用時候,通過配置QSImageProcessConfig對象,然後交由SDWebImageExtension去異步裁剪、縮放圖片,最後顯示出來。

3、其他

QSProcessImageConfig是圖片處理配置對象,可以設置option(圖片處理選項)、outputSize(圖片輸出大小)、clipBgColor(裁剪圖片需要的背景顏色)、cornerRadius(圓角半徑)、corners(需要處理的圓角)等。

圖片的處理包括裁剪圓角、添加蒙版等(後期繼續補充)。

typedef NS_ENUM(NSInteger,QSImageProcessOption) {
    QSImageProcessOptionDefault = 0,
    QSImageProcessOptionClipCorner = 1,
    QSImageProcessOptionCircle = 2,
    QSImageProcessOptionRound = 3,
    QSImageProcessOptionAddGradationMask = 4,
    QSImageProcessOptionAddWholeMask = 5
};

圖片處理使用Core Graphics實現。在使用UIGraphicsBeginImageContextWithOptions創建上下文時候,opaque默認為YES,表示不透明;如果是裁剪,需要傳入背景色,否則被裁去的部分是黑色。

四、QSImageProcess方案的使用

1、使用介紹

a) 安裝QSImageProcess

pod 'QSImageProcess'

b) 引入頭文件

#import "QSImageProcess.h"
#import "UIImageView+QSImageProcess.h"

c) 代碼示范

//加載網絡圖片1,默認config
[self.imageView qs_setImageWithURL:url
                placeholderImage:placeholderImage];

//加載網絡圖片2,自定義config
QSImageProcessConfig *config = [QSImageProcessConfig configWithOutputSize:self.imageView.frame.size cornerRadius:cornerRadius corners:UIRectCornerAllCorners];
[self.imageView qs_setImageWithURL:url
                  placeholderImage:placeholderImage
                            config:configs];

//處理本地圖片
QSImageProcessConfig *config = [QSImageProcessConfig configWithOutputSize:self.imageView.frame.size cornerRadius:cornerRadius corners:UIRectCornerAllCorners];
//異步
[[QSImageProcess sharedInstance]processImage:image config:config completed:^(UIImage *outputImage) {
    self.imageView1.image = outputImage;
}];

//同步
self.imageView2.image = [[QSImageProcess sharedInstance]processImage:image config:config];

2、效果1

簡單實現一個Demo,通過QSImageProcess實現對本地圖片的不同處理。

說明1:模擬器開啟了Color Blended Layers、Color Misaligned Images選項。

說明2:沒有開啟Color Offscreen-Rendered是因為Controller通過push進入,整個Controller在下是顯示黃色(離屏渲染),這和系統的UINavigationController有關,具體原因需要後續去發現。使用present彈出不會有這個問題。

說明3:第三行第三列(第9個)圖片出現被紅色區域覆蓋,說明這裡出現了像素混合,這是因為該圖片處理要求輸出透明的圓形圖片。其config對象如下:

QSImageProcessConfig *config9 = [QSImageProcessConfig circleConfigWithOutputSize:_cellSize];  //透明圓形圖片

3、效果2

簡單實現一個Demo,通過UIImageView (QSImageProcess)分類實現對網絡圖片的不同處理。

說明1:模擬器開啟了Color Blended Layers、Color Misaligned Images選項。

說明2:經過處理的網絡圖片,最後通過SDWebCache緩存下來,相同的繪制需求不需要重復繪制。

說明3:被紅色區域覆蓋的圖片,是因為該圖片處理要求輸出透明的圓形圖片(發生像素混合了)。

End

  • 相關文章

    iOS實錄5:iOS中本地圖片的縮放、裁剪和壓縮

  • 項目地址

    QSImageProcess

  • 我是南華coder,一名北漂的初級iOS程序猿。iOS實(踐)錄系列是我的一點開發心得,希望能夠拋磚引玉。

作者:南華coder

鏈接:http://www.jianshu.com/p/a38a7c7bccbb

來源:簡書

著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved