如何在表格视图中加载每个单元格中的图片时提高滚动速度?

4

请查看[return cell]之前的最后几行代码。在图像加载完成后,滚动速度会变慢,似乎滚动会卡住。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *MyIdentifier = @"MyIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
    }

    int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
    NSString *itemDescription=[[stories objectAtIndex: storyIndex]
                                                 objectForKey:@"title"];

    CGRect aframe = CGRectMake(80, 30, 250, 40); 
    textLabel = [[UILabel alloc] initWithFrame:aframe];
        textLabel.font = [UIFont boldSystemFontOfSize:14];
    textLabel.numberOfLines=0;
    textLabel.textColor = [UIColor darkTextColor];
    textLabel.backgroundColor = [UIColor whiteColor];
    [cell.contentView addSubview:textLabel];
    textLabel.text=itemDescription;

    CGRect frame = CGRectMake(0, 0, 70,80);
    UIImageView *TopImageView = [[UIImageView alloc] init];
    [cell.contentView addSubview:TopImageView];
    TopImageView.frame=frame;

    m_strImage = [m_imglinkArray objectAtIndex:storyIndex]; 

    TopImage = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:m_strImage]]];
    TopImageView.image=TopImage;

    return cell;
}

你们能帮我提高滚动速度吗?

谢谢

Arun


你应该改善问题的格式,因为它不易阅读。 - Panagiotis Korros
4个回答

3
我相信您可能有两个问题。首先是没有将图像加载多线程化的问题,其次是您如何使用UITableViewCell。
iPhone在每次单元格出现在屏幕上时调用cellForRowAtIndexPath-如果您向下滚动,则向上方的所有内容都会被卸载和重新加载。正如已经注意到的那样,可以通过多线程模式来解决这个问题-可以使用markj.net发布的链接和/或使用NSThread。 NSThread的优点是您可以更灵活地处理问题或加载更多仅图像数据以外的数据。(我会同时使用两种方法)
为了有效地做到这一点,您需要拥有自定义的UITableViewCell。无论如何,这都是很好的,因为您可以使表格单元格负责其内容而不是视图控制器,并且可以有效地操作单元格格式和内容。以下是关于UITableCellView的一个链接:http://blog.atrexis.com/index.cfm/2009/1/6/iPhone--Customize-the-UITableCellView 当你实现UITableViewCell时,尽量将所有addSubView和格式化调用放在“if(cell == nil)”块中,只有在无法放置在自定义initWithFrame中时才这样做。您会发现iPhone正在堆叠您添加的每个子视图 - 它没有清除旧视图。您可以通过将所有背景颜色设置为“UIColor clearColor”,然后在点击之间更改文本来查看此功能 - 您将看到一堆文本叠在彼此上方。这通常不可见,因为填充实心背景会覆盖所有“旧”子视图。
在合并这两种方法之前,请考虑实现“模型”。您拥有一个视图和一个控制器,但是所有数据都应该在模型中。所有图像URL、内容等都应该在诸如NSMutableArray、您自己的自定义对象或可能通过SQLite之类的东西中。一旦您拥有了模型,就可以实现图像的缓存。使用缓存,所有图像将在加载应用程序之间保留,这将节省电池、带宽和时间。
我会: 1. 将所有数据放入某种模型中(NSMutableArray,SQLLite等) 2. 实现自己的自定义UITableViewCell 3. 确保在cellForRowAtIndexPath的活动块中没有0个addSubView,init或alloc调用 4. 使用委托示例或NSThread在后台加载所有图像 5. 添加本地图像缓存
有一些好的示例在外部和苹果论坛上关于缓存图像。

2

nessence提供了许多有用的信息。以下是一些更多的想法:

你在这里泄漏得很厉害。每创建一个单元格,你就会泄漏2个UILabels、一个UIImageView和一个UIImage。

正如之前所指出的那样,你不仅泄漏了这些东西,而且它们在你的视图中累积,因为你用addSubview:把它们叠在一起。

在单元格绘制期间连接到网络非常缓慢,并阻塞了你的UI。如果这些URL是本地的,那么你可以使用UIImage的+imageWithContentsOfFile方法,如果不是,你需要在后台加载它们。

我认为你在这里不需要线程。NSURLConnection是一种在后台加载数据而不产生线程开销的极好方法。

nessence完全正确,你需要一个Story模型类。

你对可重用单元格配置的基本方法是错误的。你不应该获取一个可重用的单元格,然后向其中添加子视图。所有子视图都应该在if()块中创建单元格时添加。然后,在每次通过时,只需更改事物的值。我已经重新编写了你的一些代码以进行演示。这仍然不是正确的代码,因为它在单元格绘制期间连接到网络,而且这些元素可能太多了,不能在子视图单元格(而不是自定义单元格)中。但它更接近正确的想法。我甚至不知道它是否编译通过;我只是在这里输入了它。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *MyIdentifier = @"MyIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil) {
        // Here we do all our cell creation
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];

        // Make the label
        CGRect aframe = CGRectMake(80, 30, 250, 40);
        UILabel *textLabel = [[[UILabel alloc] initWithFrame:aframe] autorelease]; // Note the -autorelease so we don't leak

        textLabel.font = [UIFont boldSystemFontOfSize:14];
        textLabel.numberOfLines=0;
        textLabel.textColor = [UIColor darkTextColor];
        textLabel.backgroundColor = [UIColor whiteColor];
        textLabel.tag = DescriptionTag; // A tag so we can find it later (you'll need a constant for this)
        [cell.contentView addSubview:textLabel];

        // And the second label
        aframe = CGRectMake(80, 30, 250, 40);
        textLabel = [[[UILabel alloc] initWithFrame:aframe] autorelease];
        textLabel.font = [UIFont boldSystemFontOfSize:14];
        textLabel.numberOfLines=0;
        textLabel.textColor = [UIColor darkTextColor];
        textLabel.backgroundColor = [UIColor whiteColor];
        textLabel.tag = TitleTag;
        [cell.contentView addSubview:textLabel];

        // The image view
        CGRect frame = CGRectMake(0, 0, 70,80);
        UIImageView *topImageView = [[[UIImageView alloc] init] autorelease];
        topImageView.frame = frame;
        topImageView.tag = TopImageTag;
        [cell.contentView addSubview:topImageView];
    }

    // all the above was cell creation; we do that as seldom as possible.
    // Now we do cell configuration. We want this to be fast.

    UILabel *descriptionLabel = (UILabel*)[cell.contentView viewWithTag:DescriptionTag];
    descriptionLabel.text = itemDescription;

    UILabel *titleLabel = (UILabel*)[cell.contentView viewWithTag:TitleTag];
    titleLabel.text =[[stories objectAtIndex:indexPath.row] objectForKey:@"title"];

    NSString *imageURLString = [m_imglinkArray objectAtIndex:storyIndex]; // You should have a model class called Story, not two arrays.
    UIImage *image = [[[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURLString]]] autorelease]; // This is still way too slow if it's a remote URL 
    UIImageView *imageView = (UIImageView*)[cell.contentView viewWithTag:TopImageTag];
    imageView.image = image;    

    return cell;
}

我建议你花点时间学习TableViewSuite实用内存管理以及Cocoa编码指南。同时学习一些Cocoa基础知识也会很有帮助,因为这里的编码风格表明你可能没有扎实的基础。虽然这是一本Mac书籍,但我还是推荐《Cocoa Programming for Mac OS X》。如果你想用它来学习iPhone,我已经整理了一个教学大纲,或许能帮到你。我还没有审查过,但斯坦福大学在线的CS193P课程看起来很有前途。

1

这个问题在这里已经被问了好几次,你需要做的是为每个单元格异步加载图像,以防止滚动变慢。

这被称为“延迟加载图像”,我在这里引用了苹果的教程: 在UITableView中延迟加载图像


0

看起来每次表视图请求获取行的单元格时,您都是从URL加载。这是在主应用程序线程(用户界面线程)中发生的,它会阻塞用户界面,使其无响应。

特别是如果这个URL是您从互联网加载的资源,那么这个暂停就很大。

我建议您应该在后台线程中加载图像,并显示占位符图像,直到它们从网络获取。

您可以尝试以下URL中提供的解决方案...

http://www.markj.net/iphone-asynchronous-table-image/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接