【原创】开源中国阅读小记 - 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的方式是否是最优?

 

 

posted on 2013-06-20 19:16  chenxi_tales  阅读(594)  评论(0编辑  收藏  举报