cellforRowAtIndexPath效率?

时间:2012-01-01 20:21:37

标签: ios performance tableview cells

每当我滚动我的tableview时,它都非常迟钝。我认为这与我如何加载我的细胞有关。我尽可能使用UINib(5.0+),同时仍然提供向后兼容性。然后我使用来自NSArray的NSDictionary中的项加载我的自定义单元格的标签和图像,该NSArray是从ViewDidLoad中的NSUserDefaults加载的。

有没有办法提高这个cellForRowAtIndexPath的效率?

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

    CustomCell *cell = (CustomCell *)[aTableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (cell == nil) {
        if ([self labelCellNib]) {
            [[self labelCellNib] instantiateWithOwner:self options:nil];
        } else {
            [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
        }
        cell = [self CustomTableCell];
        [self setCustomTableCell:nil];
    }
    NSDictionary *dictionary = [myArray objectAtIndex:indexPath.row];
    NSData *data = [dictionary objectForKey:@"OCRImage"];
    cell.previewPicture.image = [self roundCorneredImage:[UIImage imageWithData:data] radius:60];

    cell.titleLabel.text = [dictionary objectForKey:@"Title"];
    cell.titleLabel.delegate = self;

    cell.dateLabel.text = [dictionary objectForKey:@"Date"];

    if (indexPath.row%2) {
        cell.backgroundImage.image = firstImage;
    }
    else {
        cell.backgroundImage.image = secondImage;
    }
    return cell;
}

编辑:

- (UIImage*)roundCorneredImage: (UIImage*)orig radius:(CGFloat) r {
    UIGraphicsBeginImageContextWithOptions(orig.size, NO, 0);
    [[UIBezierPath bezierPathWithRoundedRect:(CGRect){CGPointZero, orig.size} 
                                cornerRadius:r] addClip];
    [orig drawInRect:(CGRect){CGPointZero, orig.size}];
    UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return result;
}

Edit2 :这些是导致延迟的行:

NSData *data = [dictionary objectForKey:@"OCRImage"];
cell.previewPicture.image = [self roundCorneredImage:[UIImage imageWithData:data] radius:60];

3 个答案:

答案 0 :(得分:3)

正如@Till在评论中所说,你应该在乐器(产品 - &X; Xcode中的配置文件)中启动你的应用,然后选择CPU - > Time Profiler仪器。

然后,在该位置滚动几秒钟,然后点击乐器中的“录制”工具栏图标以关闭您的应用。您将能够看到滚动部分,因为CPU使用率可能会固定为100%(除非由于网络活动问题而导致速度很慢)。

单击高CPU活动区域开始后的时间线,然后单击“开始检查范围”工具栏按钮,然后在高CPU活动区域结束前单击并单击“停止检查范围”工具栏按钮。

现在,您可以深入查看窗口底部的调用树视图,以确切了解所有CPU使用情况。根据我的经验,如果关闭左侧的“反向调用树”选项,通常更容易找到问题。

性能错误很难找到,有时候一行显然很慢的代码根本不会导致任何问题。解决性能问题而不浪费时间的唯一方法是使用Instruments。

答案 1 :(得分:2)

确保您已将单元格的重用标识符设置为您在代码中指定的相同内容,即@"Cell"。如果它们不匹配,那么你将不会正确地重复使用单元格,并且可能花费更多时间来创建不必要的单元格。

如果您正确地回收了单元格,那么您应该看看 if (cell == nil) {...}块之后的代码。一旦表创建了足够的单元格来填充屏幕(并且可能还有一两个),您将跳过整个块,因此滚动时大部分时间归因于此方法将归因于以下代码。知道myArray是什么,如果它实际上是一个数组,那么objectForKey:方法的作用会很有趣。没有别的东西看起来就好像需要花费很长时间,但找出周期的最佳方法是在仪器中分析你的代码。

答案 2 :(得分:1)

查看代码后的一些笔记:

  1. roundCorneredImage:radius:是否缓存了结果?如果没有,对每个单元执行CG调用肯定会出现瓶颈。 更新:使用工具确定,但可能更快(允许内存)将已处理的UIImage存储在集合中,以便下次该方法可以再次将其拉出使用相同的参数调用。

  2. 您的所有UIImage都可以在其他地方声明,然后以此方法显示。您当前的代码为每个单元格实例化了一个新的UIImage,这也可能会阻碍您的滚动。 已更新:由于Image1.pngImage2.png基本上是静态的,您可以在界面中将它们声明为静态ivar,然后将它们分配给背景图像,而不是实例化{每次{1}}。

  3. 继承UIImage并将其实例化而不是进入UITableViewCell可能会更快。此外,您还可以将布局/数据逻辑与委托方法分开。我在UINib子类中所做的Here's a gist。基本上,我将实体存储在单元格中,并且单元格知道它的标签等。这使得单元格布局逻辑不在我的数据源代码中。

  4. 您似乎正在使用UITableViewCell作为数据源。如果该词典中有很多对象,使用NSDictionaryCoreData可能要快得多。关于此事Here's a good post更新:好的,这应该不是问题。

  5. -

    修改

    所以如果你删除了所有这些:

    NSFetchedResultsController

    它仍然滞后,让我们看看你的构造函数......这些行做了什么?

    NSDictionary *dictionary = [myArray objectForKey:@"OCRImage"];
    cell.previewPicture.image = [self roundCorneredImage:[UIImage imageWithData:data] radius:60];
    
    if (indexPath.row%2) {
        cell.backgroundImage.image = firstImage;
    }
    else {
        cell.backgroundImage.image = secondImage;
    }
    

    另外,你没有使用任何透明图像或桌面单元格中的任何东西吗?众所周知,这会导致绘图滞后......

    -

    编辑#2

    如果你理解这一点,会发生什么?

    cell = [self CustomTableCell];
    [self setCustomTableCell:nil];