【问题标题】:iOS - DrawRect performance issueiOS - DrawRect 性能问题
【发布时间】:2012-06-15 21:33:13
【问题描述】:

我第一次使用-drawRect 来尝试加速 UITableView。但是,drawRect 方法似乎在很大程度上减慢了表格的速度。

请您告诉我如何改进下面的drawRect 方法以加快表格速度?

编辑---

在 drawRect 方法中,我将两个 NSStrings 写入单元格的视图,两个 UIImages 和一个投影到 NSStrings 和一个 UIImages。

上述图像之一被异步下载,然后调用setNeedsDisplay 将该 UIImage 绘制到屏幕上。我相信这最初可能是滞后发生的原因。

- (void) drawRect:(CGRect) rect {

    CGContextRef context = UIGraphicsGetCurrentContext();

    [[UIColor clearColor] set];

    CGContextFillRect(context, rect);

    CGContextSaveGState(context);
    CGContextSetShadow(context, CGSizeMake(1,1),1);
    //draw text here

    if (shouldDrawImage == YES) {

        CGContextDrawImage(context, CGRectMake(10, 10, 40, 40), self.image.CGImage);

    }

    CGContextDrawImage(context, CGRectMake(self.frame.size.width - 16, 0, 16, self.frame.size.height), [UIImage imageNamed:@"right_bar_including_holes"].CGImage);

    NSString *authorName = [[self.info objectForKey:@"user"] objectForKey:@"full_name"];

    [RGB(219, 240, 73) set];

    CGSize maximumLabelSize = CGSizeMake(self.frame.size.width - 10 - 55 - 16,9999);
    CGSize authorsize = [authorName sizeWithFont:[UIFont boldSystemFontOfSize:15]
                                     constrainedToSize:maximumLabelSize 
                                         lineBreakMode:UILineBreakModeWordWrap]; 
    [authorName drawInRect:CGRectMake(60, 10, self.frame.size.width - 60, authorsize.height) withFont:[UIFont boldSystemFontOfSize:15]];

    [RGB(249,249,249) set];

    NSString *description = [self.info objectForKey:@"description"];
    CGSize descriptionSize = [description sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:maximumLabelSize lineBreakMode:UILineBreakModeWordWrap];

    [description drawInRect:CGRectMake(60, authorsize.height + 15, descriptionSize.width, descriptionSize.height) withFont:[UIFont systemFontOfSize:14]];

    CGContextRestoreGState(context);

}

- (NSString *) reuseIdentifier {
    return NSStringFromClass([SlideCell class]);
}

- (void) updateCellInfo:(NSDictionary *)_info {
    [self setInfo:_info];

    UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
    [iv setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[[self.info objectForKey:@"user"] objectForKey:@"avatar"]]] placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *_image) {
        dispatch_async(dispatch_get_main_queue(), ^{
            shouldDrawImage = YES;
            self.image = [self roundedImage:_image];
            [iv release];
            [self setNeedsDisplay];
        });

    } failure:nil];

    [self setNeedsDisplay];

    [self setSelectionStyle:UITableViewCellSelectionStyleNone];
}

【问题讨论】:

  • 如果您解释了为什么要使用 drawRect 以及您正在使用它具体做什么,而不是期望有人通过您的代码来查看可能存在什么问题,这将对您的问题有所帮助。
  • @skinnyTOD 我已经编辑了问题,感谢您的意见。
  • 覆盖 drawRect 以提高性能对我来说似乎被误导了。您假设您编写的代码比编写 UITableView 的人更高效。我敢打赌,有一个更简单、更有效的解决方案。

标签: ios uitableview core-graphics drawrect lag


【解决方案1】:

是的 - 您在您的应用上运行 Instruments 的时间配置文件,以准确告诉您花费了多少时间,以及在哪里。它会告诉你它是图像、字符串、阴影还是其他东西。

【讨论】:

    【解决方案2】:

    您应该先分析该代码并查看图像是否是问题所在。

    我不确定 AFNetworking 库(您正在使用的)在异步下载图像时如何工作。

    如果您知道图像是问题所在,我怀疑图像在设置时需要在 UIImageView 中重新缩放。这可能是问题所在。您需要将要设置为 UIImageView 的 UIImage 重新缩放为 UIIImageView 的框架,这样就不会触发自动重新缩放。滚动时成本很高。

    您收到图像并立即将代码分派到主线程。潜在的重新调整可以“在幕后”工作。我会将该方法更改为:

    UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, IMGSIZEX, IMGSIZEY)];
        [iv setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[[self.info objectForKey:@"user"] objectForKey:@"avatar"]]] placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *_image) {
            //Note you have to implement rescaleToFitSize
            UIImage* rescaled = [_image rescaleToFitSize:iv.frame.size];
            dispatch_async(dispatch_get_main_queue(), ^{
                self.image = _image;
                [iv release];
                [self setNeedsDisplay];
            });
    
        } failure:^{
             //Handle failure! You create mem. leak on failure
             [iv release];
    }];
    

    附带说明,您不会处理图像下载中的故障。你绝对应该。

    【讨论】:

    • 同意。您可以从占位符 empy 图像开始,并在异步下载完成后对其进行更新(如果有问题的单元格仍需要该图像)。
    【解决方案3】:

    只要你正确使用它,Stock UITableView 就会尽可能高效: 1. 回收单元格(dequeue) 2. 尽可能避免透明(alpha 混合确实会减慢速度) 3.重用cell的配置不需要太多的处理时间。

    我认为没有人可以通过覆盖 drawRect 来显着改进 Apple 的代码...

    【讨论】:

    • 如果单元格中有很多子视图,滚动性能可能会受到影响。拥有一个自定义内容视图并手动绘制它可以提高性能。
    • 是的,但是使视图不透明有很大帮助(例如,设置标签背景颜色以匹配内容视图的背景颜色,而不是 clearColor)。在任何情况下,您都应该覆盖单元格的 drawRect,而不是表格的。
    • 完全同意,我认为提问者正在覆盖一个单元格,而不是表格,只是不清楚。
    • 即使你坚持使用 UIKit,考虑到它的底层都是 OpenGL ES 也会有很大帮助。所有 iOS 设备 GPU 都受填充率限制(过度绘制非常昂贵)。混合越少,驱动程序就越能使用隐藏表面移除和其他优化。
    猜你喜欢
    • 1970-01-01
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多