iOS imageio nsurlsession 漸進式圖片下載

一.圖片經常使用加載格式分兩種 通常線性式 和交錯/漸進式緩存

自上而下線性式session

先模糊再清晰app

就機率上而言線性式使用最多,應爲他所佔空間普片比漸進式小。而這兩種方式對於app端開發人員無需關心,這種圖片存儲格式是由UI來決定的。this

舉個🌰 漸進式圖片保存方式:url

1.Photoshop存儲爲Progressive JPEG,首先打開一個圖片,選擇「文件 -> 存儲爲」,選擇「JPEG」格式,點擊「保存」按鈕。在「JPEG選項」界面的「格式選項」中選擇「連續」,而後在「掃描」選項中設置爲「5」。spa

 

二.iOS代碼實現code

在app使用中網卡的狀況下若是仍是等到圖片下載好了再顯示圖片可能給用戶形成很差的體驗,因此常見的方式就是來了多多給用戶顯示多少。下面經過代碼實現圖片下載一點顯示一點.blog

 

a.這裏首先會用到Imageio相關東西大致介紹下:圖片

1.CGImageSourceRef ip

An opaque type that represents an image source.

他的做用就是用來讀取圖片的數據的,image的數據除了圖片數據外還有一些地址位置、設備信息、時間等信息、而這個類就是抽象出來幹這個的方便咱們獲取到咱們關心的數據.

2.CGImagesSourceUpdateData

void CGImageSourceUpdateData(CGImageSourceRef isrc, CFDataRef data, bool final);
Description    
Updates an incremental image source with new data.
Parameters    
isrc    
An image source.
data    
The data to add to the image source. Each time you call the function CGImageSourceUpdateData, the data parameter must contain all of the image file data accumulated so far.
final    
A value that specifies whether the data is the final set. Pass true if it is, false otherwise.

將圖片數據繼續追加到imageSource中去。

isrc imagesource類

data 類型式cfdata能夠用nsmutabledata強制轉換,爲何是nsmutabledata能夠本身想一想。此data必須需從頭至尾一直包含了image信息的data。

final 這次追加的data是否是最後一次,因此告訴咱們在追加的過程當中要作好判斷,判斷這個數據是否是最後一個.

3.CGImageSourceCreateImageAtIndex

CGImageRef CGImageSourceCreateImageAtIndex(CGImageSourceRef isrc, size_t index, CFDictionaryRef options);
Description	
Creates a CGImage object for the image data associated with the specified index in an image source.
Parameters	
isrc	
An image source.
index	
The index that specifies the location of the image. The index is zero-based.
options	
A dictionary that specifies additional creation options. See Image Source Option Dictionary Keys for the keys you can supply.
Returns	
Returns a CGImage object. You are responsible for releasing this object using CGImageRelease.

經過imagesource轉化出一個cgimage

index表示這個image的位置。默認寫0

options是配置image的特殊信息的,好比kCGImageSourceShouldCache表示能夠緩存,默認寫NULL便可。

 

 

b.接下來會用到NSUrlSession的相關功能.這裏要拿去到NSURLSessionDataDelegate的兩個回調。

1.請後被相應後的回調  

- (void)URLSession:(NSURLSession *)session
          dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler    

經過他能獲得response,經過reponse可以知道這次請求的數據長度。 內部必定要實現completionHandler(NSURLSessionResponseAllow),不然下面的回調將不會觸發。

2每一次接收到數據的回調

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data  

經過data來完成一次次給iamgesource的拼裝

 

 下面是代碼實現:

#pragma mark -- 按條漸進式圖片加載
-(void)startLoading:(NSURL *)url {
    NSURLSessionConfiguration * sessionConfig = [NSURLSessionConfiguration ephemeralSessionConfiguration];
    NSURLSession * session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
    NSURLRequest * request = [NSURLRequest requestWithURL:url];
    NSURLSessionDataTask * task = [session dataTaskWithRequest:request];
    [task resume];
    _recieveData = [[NSMutableData alloc]init];  //用於接受data
    _imageSourceRef = CGImageSourceCreateIncremental(NULL); //建立可變的sourceref
    _isLoadingFinished = NO; //用於判斷是否加載完畢
}

 

 //接受到響應獲取data總長度

- (void)URLSession:(NSURLSession *)session
          dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
    
    _expectedLength = response.expectedContentLength;
    if (completionHandler) {
        completionHandler(NSURLSessionResponseAllow);
    }
}

  //拼接data生成圖片

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data {
    

    [_recieveData appendData:data];
    if (_expectedLength <= _recieveData.length) {
        _isLoadingFinished = YES;
    }

    CGImageSourceUpdateData(_imageSourceRef, (__bridge CFDataRef)_recieveData, _isLoadingFinished);
    CGImageRef imageRef = CGImageSourceCreateImageAtIndex(_imageSourceRef, 0, NULL);
    NSLog(@"%@",[NSThread currentThread]);
    dispatch_sync(dispatch_get_main_queue(), ^{
        _imageView.image = [UIImage imageWithCGImage:imageRef];
     });
    CGImageRelease(imageRef);
   
    NSLog(@"loading");
}

  

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    _isLoadingFinished = YES;
    if (!_isLoadingFinished) {
        CGImageSourceUpdateData(_imageSourceRef, (__bridge CFDataRef)_recieveData, _isLoadingFinished);
        CGImageRef imageRef = CGImageSourceCreateImageAtIndex(_imageSourceRef, 0, NULL);
        dispatch_sync(dispatch_get_main_queue(), ^{
            _imageView.image = [UIImage imageWithCGImage:imageRef];
        });
        CGImageRelease(imageRef);
    }
}
相關文章
相關標籤/搜索