iOS图片逐渐加载的效果实现

来源:互联网 发布:ubuntu 17.04更新源 编辑:程序博客网 时间:2024/04/30 15:05

首先,放一张效果图,在手机的开发者模式下调成3G网络来模拟慢网速,可以清楚的看到图片是一点一点的显示的,也就是下载多少,显示多少。
这里写图片描述

Demo下载地址

首先图片处理,需要用到ImageIO框架,主要介绍三个函数,CGImageSourceCreateIncrementalCGImageSourceUpdateDataCGImageSourceCreateImageAtIndex

下面分别介绍这三个函数

/* Create an incremental image source. No data is provided at creation * time; it is assumed that data will eventually be provided using * "CGImageSourceUpdateDataProvider" or "CGImageSourceUpdateData".  The * `options' dictionary may be used to request additional creation options; * see the list of keys above for more information. *///创建一个递增的ImageSourceIMAGEIO_EXTERN CGImageSourceRef __nonnull CGImageSourceCreateIncremental(CFDictionaryRef __nullable options)  IMAGEIO_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_4_0);/**************************************************************************//* Update the incremental image source `isrc' with new data.  The new data * must include all the previous data plus any additional new data. The * `final' parameter should be true when the final set of data is provided; * false otherwise. *///有新的数据的时候,更新ImageSourceIMAGEIO_EXTERN void CGImageSourceUpdateData(CGImageSourceRef __nonnull isrc, CFDataRef __nonnull data, bool final)  IMAGEIO_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_4_0);/**************************************************************************//* Return the image at `index' in the image source `isrc'.  The index is * zero-based. The `options' dictionary may be used to request additional * creation options; see the list of keys above for more information. *///更具索引从ImageSource中返回ImageIMAGEIO_EXTERN CGImageRef __nullable CGImageSourceCreateImageAtIndex(CGImageSourceRef __nonnull isrc, size_t index, CFDictionaryRef __nullable options)  IMAGEIO_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_4_0);

既然上面的函数,需要Data来更新图片,这里我就用NSURLSessionDataTask来进行图片的下载,主要用到NSURLSessionDataDelegateURLSession:dataTask:dataTask didReceiveData:来获取下载中的数据,关键代码如下:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {    NSURL *url = [NSURL URLWithString:@"http://c.hiphotos.baidu.com/zhidao/pic/item/7aec54e736d12f2e0bd5528c48c2d5628435680e.jpg"];    //创建NSURLSession对象,代理方法在self(控制器)执行,代理方法队列传的nil,表示和下载在一个队列里,也就是在子线程中执行。    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];    //创建一个dataTask任务    NSURLSessionDataTask *task = [session dataTaskWithURL:url];    //启动任务    [task resume];}- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {    //存储已经下载的图片二进制数据。    [self.haveReceivedData appendData:data];    //总共需要下载的图片数据的大小。    int64_t totalSize = dataTask.countOfBytesExpectedToReceive;    //创建一个递增的ImageSource,一般传NULLCGImageSourceRef imageSource = CGImageSourceCreateIncremental(NULL);    //使用最新的数据更新递增的ImageSource,第二个参数是已经接收到的Data,第三个参数表示是否已经是最后一个Data了。    CGImageSourceUpdateData(imageSource, (__bridge CFDataRef)self.haveReceivedData, totalSize == self.haveReceivedData.length);    //通过关联到ImageSource上的Data来创建一个CGImage对象,第一个参数传入更新数据之后的imageSource;第二个参数是图片的索引,一般传0;第三个参数跟创建的时候一样,传NULL就行。    CGImageRef image = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);    //释放创建的CGImageSourceRef对象    CFRelease(imageSource);    //在主线程中更新UI    dispatch_async(dispatch_get_main_queue(), ^{        //其实可以直接把CGImageRef对象赋值给layercontents属性,翻开苹果的头文件看就知道,        //一个UIView之所以能显示内容,就是因为CALayer的原因,而CALayer显示内容的属性就是contents,而contents通常就是CGImageRef。        //self.imageView.layer.contents = (__bridge id _Nullable)(image);        self.imageView.image = [UIImage imageWithCGImage:image];        //释放创建的CGImageRef对象        CGImageRelease(image);    });}

最终完成了边下载边显示图片的效果,主要用了ImageIO的函数和NSURLSession相关的网络操作。