【原创】开源中国阅读小记 - 3 - TableCell图片异步加载
首先看TableView获取cell实例的方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
涉及Cell实例化的代码:
PostCell *cell = (PostCell *)[tableView dequeueReusableCellWithIdentifier:PostCellIdentifier]; if (!cell) { // loadNib 方式加载nib从而实例化自定义Cell NSArray *objects = [[NSBundle mainBundle] loadNibNamed:@"PostCell" owner:self options:nil]; for (NSObject *o in objects) { if([o isKindOfClass:[PostCell class]]){ cell = (PostCell *)o; break; } } UITap *singleTap = [[UITap alloc] initWithTarget:self action:@selector(clickImg:)]; // 设置手势,当单击头像图片的时候打开用户详细信息页面 [cell.img addGestureRecognizer:singleTap]; } // 加载默认的图片 cell.img.image = [UIImage imageNamed:@"avatar_loading.jpg"]; Post *p = [posts objectAtIndex:indexPath.row]; if ([cell.img.gestureRecognizers count] > 0) { UITap *tap = (UITap *)[cell.img.gestureRecognizers objectAtIndex:0]; if (tap) { // 给手势设置tag,用以点击的时候能知道需要展开的具体用户(ID) tap.tag = p.authorid; } } cell.lbl_answer_chinese.text = self.catalog <= 1 ? @"回答" : @"回帖"; cell.txt_Title.text = p.title; cell.txt_Title.font = [UIFont boldSystemFontOfSize:14.0]; cell.lbl_AnswerCount.text = [NSString stringWithFormat:@"%d", p.answerCount]; cell.lblAuthor.text = [NSString stringWithFormat:@"%@ 发布于%@", p.author, p.fromNowOn]; if (p.imgData) { // 将已加载且在内存中的image直接赋值 cell.img.image = p.imgData; } else // 图片不再内存中... { if ([p.img isEqualToString:@""]) { p.imgData = [UIImage imageNamed:@"avatar_noimg.jpg"]; } else { // TangQiao ImageCache :) // 尝试从内存池中获取图片 NSData * imageData = [_iconCache getImage:[TQImageCache parseUrlForCacheName:p.img]]; if (imageData) { p.imgData = [UIImage imageWithData:imageData]; cell.img.image = p.imgData; } else { // 判断当前位置的图片是否在读取中,如果在读取中,则downloader不为nil,则忽略(因为网络交互还在进行中) IconDownloader *downloader = [imageDownloadsInProgress objectForKey:[NSString stringWithFormat:@"%d", [indexPath row]]]; if (downloader == nil) { // 如果为空,则进行异步读取,并将其加入字典 imageDownloadsInProgress中 ImgRecord *record = [ImgRecord new]; record.url = p.img; [self startIconDownload:record forIndexPath:indexPath]; } } } } return cell;
下一步,startIconDownload: forIndexPath:中的实现,简要而言,就是做以下几件事:
1. 实例化IconDownloader,并将其set到imageDownloadsInProgress中
2. iconDownloader的实例则使用
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest: [NSURLRequest requestWithURL: [NSURL URLWithString:imgRecord.url]] delegate:self];
进行异步请求
3. 当conn执行完毕,执行它的delegate - IconDownloader的finish方法,在这个方法中缓存image
4. finish方法中,调用delegate - PostView,将ImageData通过UIImagePNGRepresentation渲染为image(png) data,并调用[tablePosts reloadData]
这里,值得商榷的是:每一张图片加载完毕都调用一次reloadData的方式是否是最优?