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;
}

你们能帮我提高卷轴的速度吗?

问候

阿伦

4

4 回答 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 调用. 使用delegation example或NSThread在后台加载所有图片 5. 添加本地图片缓存

在 about 和 Apple 论坛上有一些关于缓存图像的好例子。

于 2009-05-05T12:15:49.623 回答
2

nessence有很多很好的信息。还有一些想法:

你在这里像疯了一样漏水。您创建的每个单元格都会泄漏 2 个 UILabel、一个 UIImageView 和一个 UIImage。

如前所述,您不仅泄漏了这些,它们还在您的视图中累积,因为您使用 addSubview: 将一个放在另一个之上。

在单元格绘制期间访问网络非常慢,并且会阻塞您的 UI。如果这些URL是本地的,那么你可以使用UIImage的+imageWithContentsOfFile,如果不是,你需要在后台加载这个。

我不认为你需要一个线程在这里。NSURLConnection 是一种在后台加载数据而不会产生线程开销的绝佳方式。

本质是完全正确的,您需要 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 课程看起来很有希望。

于 2009-05-05T14:06:39.747 回答
1

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

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

于 2010-02-17T13:08:27.753 回答
0

每次表格视图要求获取一行的单元格时,您似乎都是从 url 加载的。这发生在主应用程序线程(用户界面线程)中,它阻塞了用户界面,使其没有响应。

特别是如果此 url 是您从 Internet 加载的资源,则此暂停很大。

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

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

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

于 2009-05-05T07:05:40.837 回答