美文网首页iOS 开发iOS开发进阶首页投稿(暂停使用,暂停投稿)
iOS原生GIF动图加载,大图片缓慢加载,局部显示

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

作者: 多维的宇宙 | 来源:发表于2017-11-06 16:56 被阅读57次

    好久没写下技术文档了,被感情问题困扰了,我们程序员找个女朋友咋就这么难呢,哎,不说了,说多了都是泪。还是进入正题吧。
    要做到标题说的那种效果,需要用到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动图加载,大图片缓慢加载,局部显示

        本文链接:https://www.haomeiwen.com/subject/vbllmxtx.html