iPhone:从网址加载时重复的单元图像视图

时间:2010-05-14 14:21:25

标签: iphone uitableview uiimageview rss

我正在为iPhone开发一个演示RSS阅读器。我显然有一个tableview来显示feed,然后是详细的视图。其中一些Feed有一个缩略图,我希望在表格的cell.imageview上显示,有些则没有。

问题是滚动表时,加载的缩略图开始在其他单元格上重复,我最终在每个单元格上都有缩略图。

这是我的一段代码。我可以稍后上传截图

   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: @"rssItemCell"];
        if(nil == cell){
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"rssItemCell"]autorelease];
        }
        BlogRss *item = [[[self rssParser]rssItems]objectAtIndex:indexPath.row];
        cell.textLabel.text = [item title];
        cell.detailTextLabel.text = [item description];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

        // Thumbnail if exists
        if(noticia.imagePath != nil){
            NSData* imageData;
            @try {
                imageData = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:item.imagePath]];
            }
            @catch (NSException * e) {
                //Some error while downloading data
            }
            @finally {
                item.image = [[UIImage alloc] initWithData:imageData];
                [imageData release];
            }
        }

        if(item.image != nil){
            [[cell imageView] setImage:item.image];
        }
        return cell;
    }

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

很容易。

细胞被重复使用。每次填充单元格时,请确保清除cell.imageView.image。您可能只需要删除if(item.image!= nil)行。

对于生产应用程序,您可能还希望在后台获取图像并实现简单的缓存。有很多关于如何做到这一点的例子。

修改

RickiG提出了很多好处:cellForRowAtIndexPath应该显示模型中的数据,尽可能少!

只提供一个视图就绪模型的概念很好(我用ASP.NET MVC做),但需要与iPhone的JustInTime内存最小化技术进行平衡,让我们面对它,你不是在提交试图从你的tableview上的控件读回数据真正的罪 - 这真的不起作用!

你正在做的最糟糕的事情是在cellForRowAtIndexPath上阅读网络数据,因为这将阻止英国。相反,您应该显示空白或占位符图像并触发将使用数据更新模型的后台提取,然后触发重新加载 - 最好是特定单元格。

答案 1 :(得分:1)

UITableView是为了反映“模型”,所以永远不要试图 在构建单元格之后更改单元格上的数据/视图是自我的,或者根据索引号等引用单元格,创建数据数组,我通常会构建一个单独的CellViewEntity对象来保存单元格上所需的所有数据,如标题,详细信息文本等,但也有行为的东西,它是扩展的,它有特殊的视图可见等。

然后我构建了一个UIView CellView,我用我需要的图形和方法填充,例如 - (void)shouldDisplayCheckmark :( BOOL)值等。 我设置了CellVIew对象的标签 - [cellView setTag:15]并释放了CellView。现在我可以在不保留它的情况下引用它,让UITableVIew决定应该释放/保留的内容。

当更新时滚动,当单元格进入或离开屏幕时,SDK会不断调用cellForRowAtIndexPath。所以不要在此函数中加入大量的实例化,Web调用等。

在这个if块中。

   if(nil == cell){
      cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"rssItemCell"]autorelease];
        }

我实例化一个单元格和一个CellView,并将CellView对象添加到单元格视图中。 (带标签)

在if(cell == nil)之外的

我只使用模型数组中的数据更新CellVIew。

这意味着如果单元格存在,它将被重用并从数组中更新其属性,否则它将被创建并附加到单元格。 在if语句之外,我像这样引用我的CellView:

[(CellView*)[cell viewWithTag:15] updateValuesAccordingToModelArray:[array objectAtIndes:indexPath.row]]; //this will be the only code executed for a already existing cell.

我想它可能看起来有点超出限制,但是你不能以一致的方式引用像这样的[uitableView cellAtRow:14]这样的单元格,因为UITableView会缓存屏幕外的单元格并相应地更改indexPath。这种方法可以用你的数组。

现在停止漫步:) ...将一个漂亮的tableView友好包中的所有数据分开并将其提供给表视图 - 仅限一种方式。