在 GCD 块中绘制图像时卡顿

Posted

技术标签:

【中文标题】在 GCD 块中绘制图像时卡顿【英文标题】:Stuttering when Drawing to Image in GCD Block 【发布时间】:2012-12-23 00:25:48 【问题描述】:

我有以下方法,它需要一些CAShapeLayers 并将它们转换为UIImageUIImage 用于UITableView 的单元格中(就像您从某个库中选择照片时的照片应用程序一样)。从GCD 块中调用此方法:

-(UIImage*) imageAtIndex:(NSUInteger)index

    Graphic *graphic = [[Graphic graphicWithType:index]retain];

    CALayer *layer = [[CALayer alloc] init];
    layer.bounds = CGRectMake(0,0, graphic.size.width, graphic.size.height);
    layer.shouldRasterize = YES;
    layer.anchorPoint = CGPointZero;
    layer.position = CGPointMake(0, 0);

    for (int i = 0; i < [graphic.shapeLayers count]; i++)
    
        [layer addSublayer:[graphic.shapeLayers objectAtIndex:i]];
    

    CGFloat largestDimension = MAX(graphic.size.width, graphic.size.height);
    CGFloat maxDimension = self.thumbnailDimension;
    CGFloat multiplicationFactor = maxDimension / largestDimension;
    CGSize graphicThumbnailSize = CGSizeMake(multiplicationFactor * graphic.size.width, multiplicationFactor * graphic.size.height);

    layer.sublayerTransform = CATransform3DScale(layer.sublayerTransform, graphicThumbnailSize.width / graphic.size.width, graphicThumbnailSize.height / graphic.size.height, 1);
    layer.bounds = CGRectMake(0,0, graphicThumbnailSize.width, graphicThumbnailSize.height);

    UIGraphicsBeginImageContextWithOptions(layer.bounds.size, NO, 0);
    [layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = [UIGraphicsGetImageFromCurrentImageContext() retain];
    UIGraphicsEndImageContext();

    [layer release];
    [graphic release];

    return [image autorelease];

无论出于何种原因,当我滚动UITableView 并加载图像时,它有点卡顿。我知道GCD 代码很好,因为它以前工作过,所以看起来这段代码中的某些东西导致了口吃。有谁知道那可能是什么? CAAnimation 不是线程安全的吗?或者有谁知道更好的方法来获取一堆CAShapeLayers 并将它们转换为UIImage

【问题讨论】:

您是否使用 Instruments 检查过帧率。此外,当您说您正在使用 GCD 时,您是在异步队列上运行整个事情吗?我敢肯定你是。另外,当您说口吃时,能否请您详细说明您所看到的,是新细胞进入视野吗... @Srikanth - 是的,图像加载到表格中时的帧速率是 35-40。但是,在我缓存它们之后,它是 60。是的,它在异步队列上。口吃是指当我尽可能快地滚动表格视图并且滚动不会流畅时,它会停止和继续(大概是为了加载)。 【参考方案1】:

最后我相信:

[layer renderInContext:UIGraphicsGetCurrentContext()];

无法在单独的线程上完成,所以我必须执行以下操作:

UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
//draw the mutable paths of the CAShapeLayers to the context
UIImage *image = [UIGraphicsGetImageFromCurrentImageContext() retain];
UIGraphicsEndImageContext(); 

WWDC2012 视频“在 ios 上构建并发用户界面”中有一个很好的例子(我学会了这样做)

【讨论】:

以上是关于在 GCD 块中绘制图像时卡顿的主要内容,如果未能解决你的问题,请参考以下文章

华为快应用在setInterval中绘制canvas动画卡顿,怎么破

Android端 APP GPU过度绘制GPU过度绘制及优化

iOSUI视图面试及原理总结

app卡顿原因

app卡顿原因

app卡顿原因