在 UITableView 中使用带有 [UIImage resizableImageWithCapInsets] 的 UIImageView 会导致延迟

Posted

技术标签:

【中文标题】在 UITableView 中使用带有 [UIImage resizableImageWithCapInsets] 的 UIImageView 会导致延迟【英文标题】:Using UIImageView's with [UIImage resizableImageWithCapInsets] in a UITableView causes lag 【发布时间】:2013-10-04 16:01:38 【问题描述】:

这是我用来生成 UITableViewCell 的代码。我正在 ios6/iOS7 中进行测试。如果我删除有关 UIImageView 的代码 UITableView 滚动就好了。但是使用 UIImageView 它会滞后和痉挛。我正在寻找一些解决方案来解决滞后问题。提前谢谢你。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    
        static NSString *CellIdentifier = @"BubbleCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        UILabel *label;
        UIImageView *bubbleLeft;
        UIImageView *bubbleRight;

        if(cell == nil)
        
        cell = [[
    UITableViewCell
    alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;

            label = [[UILabel alloc] init];
            label.tag = 1;

            NSString *fileLeft = [[NSBundle mainBundle] pathForResource:@"chatBubbleGray.png" ofType:nil];
            NSString *fileRight = [[NSBundle mainBundle] pathForResource:@"chatBubbleBlue.png" ofType:nil];

    UIImage
    *bubbleImageLeft = [[
    UIImage imageWithContentsOfFile:fileLeft] resizableImageWithCapInsets:UIEdgeInsetsMake(20, 22, 20, 22)];

    UIImage
    *bubbleImageRight = [[
    UIImage imageWithContentsOfFile:fileRight] resizableImageWithCapInsets:UIEdgeInsetsMake(20, 22, 20, 22)];

            bubbleLeft = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 10, 10)];
            [bubbleLeft setImage:bubbleImageLeft];
            bubbleLeft.tag=2;
            bubbleRight = [[UIImageView alloc] initWithFrame:CGRectMake(320 - 20, 10, 10, 10)];
            [bubbleRight setImage:bubbleImageRight];
            bubbleRight.tag=3;

            [cell addSubview:bubbleLeft];
            [cell addSubview:bubbleRight];
            [cell addSubview:label];

        else
            label = (UILabel *)[cell viewWithTag:1];
            bubbleLeft = (UIImageView *)[cell viewWithTag:2];
            bubbleRight = (UIImageView *)[cell viewWithTag:3];
        


    // set frame to largest size you want

        label.numberOfLines = 0;
        label.
    backgroundColor = [UIColor clearColor];
        label.
    text
    = [[[
    currentDictionary objectAtIndex:indexPath.row] objectForKey:@"string"] stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"];

        CGSize maximumLabelSize = CGSizeMake(296, FLT_MAX);

        CGSize expectedLabelSize = [label.text sizeWithFont:label.font constrainedToSize:maximumLabelSize lineBreakMode:label.lineBreakMode];

        if (indexPath.row%2==0) 
            bubbleRight.hidden = YES;
            bubbleLeft.hidden = NO;
            bubbleLeft.frame = CGRectMake(10, 10, expectedLabelSize.width+20, expectedLabelSize.height+20);

            label.frame = CGRectMake(
                                     20, 20,
                                     expectedLabelSize.width, expectedLabelSize.height);

        else
            bubbleLeft.hidden = YES;
            bubbleRight.hidden = NO;

            bubbleRight.frame = CGRectMake(320 - expectedLabelSize.width - 30, 10, expectedLabelSize.width+20, expectedLabelSize.height+20);

            label.frame = CGRectMake(
                                     320 - expectedLabelSize.width - 20, 20,
                                     expectedLabelSize.width, expectedLabelSize.height);
        



    // Configure the cell...

        return cell;
    

编辑:

进一步查看代码发现滞后实际上是由这段代码引起的: bubbleLeft.frame = CGRectMake(10, 10, expectedLabelSize.width+20, expectedLabelSize.height+20);

【问题讨论】:

【参考方案1】:

正如我之前所说,resizableImage 似乎导致了滞后。问题是我试图使用这段代码:

UIImage imageWithContentsOfFile:fileLeft] resizableImageWithCapInsets:UIEdgeInsetsMake(20, 22, 20, 22)];

对于一个图像

47x36.

这意味着我的帽子是负向翻转可拉伸部分导致滞后。作为进一步的信息,resizableImageWithCapInsets: 的最佳性能可以通过留下1px x 1px 可拉伸区域来调整大小来实现。

【讨论】:

那么你使用的 UIEdgeInset 值是多少? 应该是 17,23,17,23【参考方案2】:

您可以做的一件简单的事情是使用imageNamed: 而不是imageWithContentsOfFile: 创建您的UIImagesimageNamed: 通常只会从第一个磁盘加载图像然后将其缓存,而imageWithContentsOfFile:每次都输出到磁盘。

如果这不能让您获得所需的性能,您可能必须将图像加载过程移至不同的执行线程。

【讨论】:

而且图片也可以加载一次,因为是同一张图片,可能是setup方法。 在创建第一个单元格时,图像仅加载 1 次。然后它们在细胞被重用时被重用。此外,我刚刚尝试使用imageNamed: 再次运行代码。但结果还是一样。我又调试了一遍代码,发现问题其实是bubbleLeft.frame = CGRectMake(10, 10, expectedLabelSize.width+20, expectedLabelSize.height+20); 另外,您还可以在情节提要/xib 中拥有与不同重用标识符相关联的几个不同的自定义表格视图单元格,这样您就不必隐藏/显示和调整表格视图单元格的框架在创建时。

以上是关于在 UITableView 中使用带有 [UIImage resizableImageWithCapInsets] 的 UIImageView 会导致延迟的主要内容,如果未能解决你的问题,请参考以下文章

在 UITableView iPhone 中显示 MySQL 数据库中的图像

根据变量使用不同的图像初始化 UIImageView

如何在swift中使用带有completionHandler的UIImageView load()函数

在 ViewController 中使用带有外部 DataSource 和 UITableView 的自定义 UITableViewCell

在 UITableView 中使用带有 [UIImage resizableImageWithCapInsets] 的 UIImageView 会导致延迟

如何在 UITableView 中显示带有视频图像的视频文件?