国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > iOS > 正文

iOS異步下載圖片實例代碼

2020-07-26 03:17:05
字體:
供稿:網(wǎng)友

寫在前面

在iOS開發(fā)中,無論是在UITableView還是在UICollectionView中,通過網(wǎng)絡(luò)獲取圖片設(shè)置到cell上是較為常見的需求。盡管有很多現(xiàn)存的第三方庫可以將下載和緩存功能都封裝好了供開發(fā)者使用,但從學(xué)習(xí)的角度出發(fā),看懂源碼,理解其中的原理,結(jié)合自身的實際需求寫出自己的代碼是很必要的。在剛結(jié)束的Demo中,有用到異步圖片下載功能,這篇筆記就是對整個實現(xiàn)的簡單整理。

基本思路

•cell中添加一個UIImageView

•cell擁有url,發(fā)起下載請求,注冊下次完成通告,在通告處理時間中獲取下載圖片并設(shè)置

•下載管理類負(fù)責(zé)開啟下載線程和各種緩存(內(nèi)存+文件),下載完成后發(fā)送下載完成通告

•為避免cell重用和異步下載造成的圖片錯位,cell在發(fā)起下載前為自身imageView設(shè)置默認(rèn)圖片,同時為imageView設(shè)置tag

整體框架

 

關(guān)鍵代碼

cell初始化,并注冊下載完成通告

@interface SQPhotoCell ()@property (strong, nonatomic) UIImageView *photoView;//Tag指向當(dāng)前可見圖片的url,可過濾掉已經(jīng)滑出屏幕的圖片的url@property (strong, nonatomic) NSString *imageViewTag;@end-(id)initWithFrame:(CGRect)frame{self = [super initWithFrame:frame];if (self){_photoView = [[UIImageView alloc] initWithFrame:CGRectZero];_photoView.userInteractionEnabled = YES;[self.contentView addSubview:_photoView];_imageViewTag = @"";//注冊下載完成通知[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(downloadCallback:)name:NOTIFICATION_DOWNLOAD_CALLBACKobject:nil];}return self;}

cell通知處理事件

//通知處理事件- (void)downloadCallback:(NSNotification *)noti{NSDictionary *notiDic = noti.userInfo;NSString *urlStr = [notiDic objectForKey:@"urlStr"];UIImage *image = [notiDic objectForKey:@"image"];if ([self.imageViewTag isEqualToString:urlStr]){self.photoView.image = image;}}

cell發(fā)起下載請求

- (void)setImageWithURL:(NSString *)urlStr placeholder:(UIImage *)placeholder{self.imageViewTag = urlStr;//預(yù)設(shè)圖片,用于清除復(fù)用以前可能存在的圖片self.photoView.image = placeholder;if (urlStr){SQWebImageManager *manager = [SQWebImageManager sharedManager];[manager downloadImageWithURLString:urlStr];}[self setNeedsDisplay];}

下載管理類下載函數(shù)

- (void)downloadImageWithURLString:(NSString *)urlStr{// 1.判斷內(nèi)存緩存 {urlStr: image}UIImage *cacheImage = [self.imageCache objectForKey:urlStr];if (cacheImage != nil){//發(fā)出下載完成的通知,并傳回urlStr和圖片[self postDownloadCompleteNotification:urlStr withImage:cacheImage];return;}// 2.判斷沙盒緩存NSString *cacheImagePath = [self cacheImagePathWithURLString:urlStr];cacheImage = [UIImage imageWithContentsOfFile:cacheImagePath];if (cacheImage != nil){// 從沙盒中讀取到了圖片,設(shè)置到內(nèi)存緩存中,方便下次可以直接從內(nèi)存中讀取[self.imageCache setObject:cacheImage forKey:urlStr];// 返回圖片[self postDownloadCompleteNotification:urlStr withImage:cacheImage];return;}// 3.判斷操作緩存,防止圖片多次下載 {urlStr: operation}if (self.operationCache[urlStr] != nil){// 有操作正在下載這張圖片NSLog(@"有操作正在下載這張圖片");return;}// 1.定義下載圖片操作SQDownloadOperation *downloadOperation = [SQDownloadOperation downloadOperationWithURLString:urlStr cacheImagePath:cacheImagePath];// 設(shè)置操作下載完成的回調(diào),當(dāng) downloadOperation 的 main 方法執(zhí)行完成的時候回調(diào)用__weak typeof(downloadOperation) weakDownloadOperation = downloadOperation;downloadOperation.completionBlock = ^() {// 1. 獲取下載完成的圖像UIImage *image = [weakDownloadOperation getDownloadImage];// 2. 從操作緩沖池中刪除操作[self.operationCache removeObjectForKey:urlStr];// 3. 判斷圖像是否為空(縮略圖)if (image != nil){// 設(shè)置下載的圖片到圖片內(nèi)存緩存中[self.imageCache setObject:image forKey:urlStr];// 4. 主線程回調(diào)[[NSOperationQueue mainQueue] addOperationWithBlock:^{//發(fā)出下載完成通告[self postDownloadCompleteNotification:urlStr withImage:image];}];}else{//如果圖片為空,返回下載失敗時的默認(rèn)圖片image = [UIImage imageNamed:@"default.jpg"];// 4. 主線程回調(diào)[[NSOperationQueue mainQueue] addOperationWithBlock:^{//發(fā)出下載完成通告[self postDownloadCompleteNotification:urlStr withImage:image];}];}};// 2.將下載圖片操作添加到隊列中[self.downloadQueue addOperation:downloadOperation];// 3.將下載圖片操作添加到下載操作緩存中[self.operationCache setObject:downloadOperation forKey:urlStr];}- (void)postDownloadCompleteNotification:(NSString *)urlStr withImage:(UIImage *)image{NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:urlStr, @"urlStr", image, @"image",nil];[[NSNotificationCenter defaultCenter]postNotificationName:NOTIFICATION_DOWNLOAD_CALLBACKobject:niluserInfo:dic];}

控制器中使用

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{SQPhotoCell *cell = (SQPhotoCell *)[collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifierforIndexPath:indexPath];UIImage *placeholder = [UIImage imageNamed:@"gray.jpg"];NSString *imageUrl = @"http://www.taopic.com/uploads/allimg/110925/9117-11092509545328.jpg";[cell setImageWithURL:imageUrl placeholder:placeholder];return cell;}

寫在后面

這個異步下載圖片的思路是仿照SDWebImage的,雖然可以直接看到源碼,也有一些文章和博客講解思路,但自己在沒有接觸過多線程編程的情況下學(xué)習(xí)這個下載思路還是花了挺多時間的。前期一直都有些著急,想要趕緊做出來,在對好多東西都是懵懵懂懂的情況下就去做了,后來才慢慢意識到,其實慢就是快,慢下來,把問題想清楚了再去實施雖然前期感覺是不太好的,但到越到后面就越能發(fā)現(xiàn)這種慢的好處。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 徐州市| 云安县| 达日县| 威海市| 大同市| 睢宁县| 扎兰屯市| 三明市| 吴江市| 金乡县| 长治县| 富顺县| 鄱阳县| 英吉沙县| 怀来县| 土默特右旗| 宣恩县| 绥阳县| 河津市| 嘉祥县| 无为县| 舞阳县| 利川市| 南陵县| 洛宁县| 桃江县| 涿鹿县| 浦北县| 枝江市| 绥芬河市| 文登市| 皋兰县| 鹤庆县| 乐陵市| 涿州市| 慈溪市| 鄂托克前旗| 九台市| 临湘市| 闽侯县| 闸北区|