drawRect表现

Ric*_*ard 5 performance drawrect ipad ios

我需要在iPad上绘制50万到100万的多边形.经过实验,我只能获得1 fps.这只是一个例子,我的真实代码有一些大小合适的多边形.

以下是一些问题:

  1. 为什么我不必将Quartz Framework添加到我的项目中?
  2. 如果许多多边形重复,我可以利用它与视图或它们太重等?
  3. 任何替代方案,QTPaint都可以处理这个问题,但是会进入gpu.有没有像QT或ios这样的东西?
  4. Opengl可以增加这种类型的2d性能吗?

示例drawrect:

//X Y Array of boxes

- (void)drawRect:(CGRect)rect
{
    int reset = [self pan].x;
    int markX = reset;
    int markY = [self pan].y;
    CGContextRef context = UIGraphicsGetCurrentContext();
    for(int i = 0; i < 1000; i++)//1,000,000
    {
        for(int j = 0; j < 1000; j++)
        {
            CGContextMoveToPoint(context, markX,  markY);
            CGContextAddLineToPoint(context, markX, markY + 10);
            CGContextAddLineToPoint(context, markX + 10, markY + 10);
            CGContextAddLineToPoint(context, markX + 10, markY);
            CGContextAddLineToPoint(context, markX, markY);
            CGContextStrokePath(context);
            markX+=12;
        }
        markY += 12;
        markX = reset;
    }

}
Run Code Online (Sandbox Code Playgroud)

平移只是通过平移手势在屏幕上移动框的数组.任何帮助或提示将非常感谢.

Stu*_*nie 18

您的示例的关键问题是它未经过优化.无论何时drawRect:调用,设备都会渲染所有1,000,000个方格.更糟糕的是,它正在循环中对这些API进行6,000,000次调用.如果你想以一个适度的30fps刷新这个视图,那就是180,000,000次/秒.

使用"简单"示例,绘制区域的大小为12,000px×12,000px; 您可以在iPad显示屏上显示的最大区域为768×1024(假设是全屏肖像).因此,代码浪费了大量可见区域之外的CPU资源.UIKit可以相对轻松地处理这种情况.

管理明显大于可见区域的内容时,应将绘图限制为仅显示可见区域.UIKit有两种处理方式; UIScrollView与CATiledLayer支持的视图相结合是您最好的选择.

脚步:

免责声明:这是上述示例代码的优化

  • 创建一个新的基于View的应用程序 iPad项目
  • 添加对QuartzCore.framework的引用
  • MyLargeView从UIView 创建一个新类,比如子类,并添加以下代码:

:

#import <QuartzCore/QuartzCore.h>

@implementation MyLargeView
- (void)awakeFromNib {
    CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
    tiledLayer.tileSize = CGSizeMake(512.0f, 512.0f);
}

// Set the layer's class to be CATiledLayer.
+ (Class)layerClass {
    return [CATiledLayer class];
}

- (void)drawRect:(CGRect)rect {
    // Drawing code
    // only draws what is specified by the rect parameter

    CGContextRef context = UIGraphicsGetCurrentContext();

    // set up some constants for the objects being drawn        
    const CGFloat width  = 10.0f;           // width of rect
    const CGFloat height = 10.0f;           // height of rect
    const CGFloat xSpace = 4.0f;            // space between cells (horizontal)
    const CGFloat ySpace = 4.0f;            // space between cells (vertical)
    const CGFloat tWidth = width + xSpace;  // total width of cell
    const CGFloat tHeight = height + ySpace;// total height of cell

    CGFloat xStart = floorf(rect.origin.x / tWidth);     // first visible cell (column)
    CGFloat yStart = floorf(rect.origin.y / tHeight);    // first visible cell (row)
    CGFloat xCells = rect.size.width / tWidth + 1;       // number of horizontal visible cells
    CGFloat yCells = rect.size.height / tHeight + 1;     // number of vertical visible cells

    for(int x = xStart; x < (xStart + xCells); x++) {
        for(int y = yStart; y < (yStart + yCells); y++) {
            CGFloat xpos = x*tWidth;
            CGFloat ypos = y*tHeight;

            CGContextMoveToPoint(context, xpos,  ypos);
            CGContextAddLineToPoint(context, xpos, ypos + height);
            CGContextAddLineToPoint(context, xpos + width, ypos + height);
            CGContextAddLineToPoint(context, xpos + width, ypos);
            CGContextAddLineToPoint(context, xpos, ypos);
            CGContextStrokePath(context);
        }
    }
}


@end
Run Code Online (Sandbox Code Playgroud)
  • 编辑视图控制器nib并将UIScrollView添加到视图中
  • 将UIView添加到UIScrollView并确保它填充UIScrollView
    查看层次结构
  • 将类更改为MyLargeView
    将类更改为MyLargeView
  • 将MyLargeView的帧大小设置为12,000×12,000
    输入框架大小
  • 最后,打开视图控制器.m文件并添加以下覆盖:

:

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
    UIScrollView *scrollView = [self.view.subviews objectAtIndex:0];
    scrollView.contentSize = CGSizeMake(12000, 12000);
}
Run Code Online (Sandbox Code Playgroud)

如果您查看drawRect:调用,它只会绘制到rect参数指定的区域,这将对应于我们在awakeFromNib方法中配置的CATiledLayer的区块大小(512×512).这将扩展到1,000,000×1,000,000像素的画布.

另一种选择是ScrollViewSuite示例,具体来说3_Tiling.