一.图片经常使用加载格式分两种 通常线性式 和交错/渐进式缓存
自上而下线性式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); } }