iOS原生GIF動圖加載,大圖片緩慢加載瞒御,局部顯示

好久沒寫下技術文檔了父叙,被感情問題困擾了,我們程序員找個女朋友咋就這么難呢肴裙,哎趾唱,不說了,說多了都是淚蜻懦。還是進入正題吧甜癞。
要做到標題說的那種效果,需要用到Image I/O阻肩,有興趣的可以先看看官方文檔慢慢閱讀带欢,其實不難理解运授,這個主題只會用到其中一些功能烤惊。

主要是我們項目的app中需要加入廣告頁面,也就是我常常使用其他app時吁朦,打開的時候都會有個幾秒種的廣告柒室,有個跳過按鈕。圖片是從后臺下載的逗宜,包括GIF動態(tài)圖和靜態(tài)圖雄右。然后再擴展說說大圖片緩慢加載,局部顯示的做法纺讲。(ps:這里都適用iOS原生擂仍,不使用第三方)

這是demo源碼地址:demo源碼地址https://github.com/cocoaliaolei/ImageDown

第一部分:GIF動圖加載(當然如果圖片不是gif圖片照樣可以加載。)

首先是圖片下載熬甚,我們可以直接使用下面這個方法來下載圖片

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

當然要放在線程中區(qū)逢渔,下載完成后做,數據緩存(簡單的本地存儲)和數據處理

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來處理數據
首先是創(chuàng)建 Image Sources包含不止一個圖像乡括,縮略圖肃廓,各個圖像的特征和圖片文件。

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

Image Sources中可能是多張圖片诲泌,可以通過CGImageSourceGetCount來獲得圖片在Image Sources中的數量

size_t  count = CGImageSourceGetCount(myImageSource);

判斷count盲赊,如果count >1則是多張動態(tài)圖,反之則是一張靜態(tài)圖.
靜態(tài)圖簡單處理就好敷扫,如下

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];
        
        /**
         * 創(chuàng)建了CGImageRef實例就要release,不然內存爆炸??
         */
        CGImageRelease(imageRef);
    }
    
    if (Durations == 0.0f) Durations = 0.1f * count;
    
    UIImage *img = [UIImage animatedImageWithImages:aray duration:Durations];
    
    return img;
}

最后將返回的img給imageview顯示就可以了。

第二部分:單張靜態(tài)圖的緩慢加載绘迁,即一部分一部分的顯示

網絡請求我們選用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];
        }
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末依疼,一起剝皮案震驚了整個濱河市痰腮,隨后出現的幾起案子,更是在濱河造成了極大的恐慌律罢,老刑警劉巖膀值,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異误辑,居然都是意外死亡沧踏,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門巾钉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翘狱,“玉大人,你說我怎么就攤上這事砰苍×市伲” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵赚导,是天一觀的道長茬缩。 經常有香客問我,道長吼旧,這世上最難降的妖魔是什么凰锡? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮黍少,結果婚禮上寡夹,老公的妹妹穿的比我還像新娘。我一直安慰自己厂置,他們只是感情好菩掏,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著昵济,像睡著了一般智绸。 火紅的嫁衣襯著肌膚如雪野揪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天瞧栗,我揣著相機與錄音斯稳,去河邊找鬼。 笑死迹恐,一個胖子當著我的面吹牛挣惰,可吹牛的內容都是我干的。 我是一名探鬼主播殴边,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼憎茂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了锤岸?” 一聲冷哼從身側響起竖幔,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎是偷,沒想到半個月后拳氢,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡蛋铆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年馋评,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片戒职。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡栗恩,死狀恐怖,靈堂內的尸體忽然破棺而出洪燥,到底是詐尸還是另有隱情,我是刑警寧澤乳乌,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布捧韵,位于F島的核電站,受9級特大地震影響汉操,放射性物質發(fā)生泄漏再来。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一磷瘤、第九天 我趴在偏房一處隱蔽的房頂上張望芒篷。 院中可真熱鬧,春花似錦采缚、人聲如沸针炉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽篡帕。三九已至殖侵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間镰烧,已是汗流浹背拢军。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留怔鳖,地道東北人茉唉。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像结执,于是被迫代替她去往敵國和親赌渣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內容