iOS原生GIF动图加载,大图片缓慢加载,局部显示

好久没写下技术文档了,被感情问题困扰了,我们程序员找个女朋友咋就这么难呢,哎,不说了,说多了都是泪。还是进入正题吧。
要做到标题说的那种效果,需要用到Image I/O,有兴趣的可以先看看官方文档慢慢阅读,其实不难理解,这个主题只会用到其中一些功能。

主要是我们项目的app中需要加入广告页面,也就是我常常使用其他app时,打开的时候都会有个几秒种的广告,有个跳过按钮。图片是从后台下载的,包括GIF动态图和静态图。然后再扩展说说大图片缓慢加载,局部显示的做法。(ps:这里都适用iOS原生,不使用第三方)

这是demo源码地址:demo源码地址:https://github.com/cocoaliaolei/ImageDown

第一部分:GIF动图加载(当然如果图片不是gif图片照样可以加载。)

首先是图片下载,我们可以直接使用下面这个方法来下载图片

NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];

当然要放在线程中区,下载完成后做,数据缓存(简单的本地存储)和数据处理

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        

        NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
        /**
         *缓存
         */
        if (self.isNeedCache) {
            [LLimageCache cacheImageData:imgData withPath:[NSURL URLWithString:url]];
        }
        /**
         * 回到主线程处理
         */
        dispatch_async(dispatch_get_main_queue(), ^{
            [self gifImageHandle:imgData withUrl:url];
        });
    });

这里主要是讲使用Image I/O来处理数据
首先是创建 Image Sources包含不止一个图像,缩略图,各个图像的特征和图片文件。

CGImageSourceRef myImageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imgData,NULL);

Image Sources中可能是多张图片,可以通过CGImageSourceGetCount来获得图片在Image Sources中的数量

size_t  count = CGImageSourceGetCount(myImageSource);

判断count,如果count >1则是多张动态图,反之则是一张静态图.
静态图简单处理就好,如下

CGImageRef imgRef = CGImageSourceCreateImageAtIndex(myImageSource, 0, NULL);
 UIImage *img = [UIImage imageWithCGImage:imgRef];

Image Sources包含了每一张的图片信息,大小以及播放时间
所以我们需要获取每一张图片的时间

/**
 * 获取每一张图片的时间
 */
-(CGFloat)getIndexImageDuration:(CGImageSourceRef)myImageSource index:(size_t)i{
    
    CGFloat indexDuration = 0.1f;
    CFDictionaryRef cfProperties =  CGImageSourceCopyPropertiesAtIndex(myImageSource, i, NULL);
    NSDictionary *timesDic = (__bridge NSDictionary *)cfProperties;
    NSDictionary *gifProperties = timesDic[(NSString *)kCGImagePropertyGIFDictionary];
    NSNumber *UnclampedDelayTime = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
    if (UnclampedDelayTime) {
        indexDuration = UnclampedDelayTime.floatValue;
    }
    else{
        NSNumber *DelayTime = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
        if (DelayTime) {
            indexDuration = DelayTime.floatValue;
        }
    }
    if (indexDuration < 0.01f) indexDuration = 0.1f;
    CFRelease(cfProperties);
    return indexDuration;
}

再将图片组装起来

/**
 * 将图片集成gif图片
 *
 */
-(UIImage *)getCombineImages:(CGImageSourceRef)myImageSource index:(size_t)count{
    
    NSMutableArray *aray = [[NSMutableArray alloc]init];
    
    CGFloat Durations = 0.0f;
    
    for (size_t i = 0; i < count; i ++) {
        
        CGImageRef imageRef = CGImageSourceCreateImageAtIndex(myImageSource, i, NULL);
        
        [aray addObject:[UIImage imageWithCGImage:imageRef]];
        
        Durations += [self getIndexImageDuration:myImageSource index:i];
        
        /**
         * 创建了CGImageRef实例就要release,不然内存爆炸
         */
        CGImageRelease(imageRef);
    }
    
    if (Durations == 0.0f) Durations = 0.1f * count;
    
    UIImage *img = [UIImage animatedImageWithImages:aray duration:Durations];
    
    return img;
}

最后将返回的img给imageview显示就可以了。

第二部分:单张静态图的缓慢加载,即一部分一部分的显示

网络请求我们选用NSURLSession,不用connection,苹果好像要弃用她而推NSURLSession,不过用哪个都一样。

-(void)singleRequestWith:(NSString *)url{
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *sesson = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
    NSURLSessionDataTask *task = [sesson dataTaskWithRequest:request];
    [task resume];
}

在代理中获取相关数据

#pragma mark - NSURLSessionDataDelegate
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
    
    NSLog(@"%@", NSStringFromSelector(_cmd));
    self.expectedLeght = response.expectedContentLength;
    NSLog(@"---expectedLeght:%lld",self.expectedLeght);
    completionHandler(NSURLSessionResponseAllow);
}

-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
    
    [self.imgData appendData:data];
    [self.TempImgData appendData:data];
    
    if (self.imgData.length == self.expectedLeght) self.isDownloadFinished = YES;
    /**
     * 50这个值的设置是根据每次didReceiveData的数据长度估算的一个值
     * 这里不能每次接收到数据就将其转换为图片,这样对cpu消耗太大,容易引起崩溃
     */
    
    if (self.TempImgData.length > self.expectedLeght/50 || self.expectedLeght == self.imgData.length) {
        self.TempImgData = nil;
        UIImage *img = [self creatImageWithData];
        if (self.isNeedCache && self.expectedLeght == self.imgData.length) {
            [LLimageCache cacheImageData:self.imgData withPath:dataTask.response.URL];
        }
        [self returnImageWith:img];
    }
}

下载完成释放session

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    
    if (error) NSLog(@"下载出错!!!---%@",error);
    /**
     * 释放session,防止内存泄漏
     */
    [session finishTasksAndInvalidate];
}

得到数据后回调,block或代理

/**
 *回调
 */
-(void)returnImageWith:(UIImage *)img{
    if (self.block) self.block(img);
    else if (self.delegate){
        if ([_delegate respondsToSelector:@selector(LLImageLoadBitDiddidReceiveGetImages:)]) {
            [_delegate LLImageLoadBitDiddidReceiveGetImages:img];
        }
    }
}

你可能感兴趣的:(iOS原生GIF动图加载,大图片缓慢加载,局部显示)