好久沒寫下技術文檔了父叙,被感情問題困擾了,我們程序員找個女朋友咋就這么難呢肴裙,哎趾唱,不說了,說多了都是淚蜻懦。還是進入正題吧甜癞。
要做到標題說的那種效果,需要用到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];
}
}
}