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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wddyzzw/article/details/78847610

首先,放一张效果图,在手机的开发者模式下调成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. */

//创建一个递增的ImageSource

IMAGEIO_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. */

//有新的数据的时候,更新ImageSource

IMAGEIO_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中返回Image

IMAGEIO_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相关的网络操作。

展开阅读全文

没有更多推荐了,返回首页