绘制多条线时的 drawRect 性能

drawRect performance when drawing many lines

我正在尝试在自定义视图的 drawRect 方法中绘制程序生成的树。这对大约 20k 行来说非常灵活。超过这一点,绘图性能就会完全下降(即绘制树的时间将近 1000 毫秒)。

绘制树的绘制代码为:

func drawBranch( branch: Branch, context :CGContext ) {        
    CGContextMoveToPoint(context,    (branch.originPoint().x), (branch.originPoint().y))
    CGContextAddLineToPoint(context, (branch.endPoint().x), (branch.endPoint().y))

    for b in branch.children {
        drawBranch(b, context: context)
    }
}

override func drawRect(rect: CGRect) {
    print("\(NSDate()) drawRect")

    // Setup graphics context
    let ctx = UIGraphicsGetCurrentContext()

    // clear context
    CGContextClearRect(ctx, rect)

    CGContextSetRGBFillColor(ctx, 0.0, 0.0, 0.0, 1.0)

    CGContextFillRect(ctx, rect)

    CGContextSaveGState(ctx);
    CGContextTranslateCTM(ctx, 0.0, rect.size.height);
    CGContextScaleCTM(ctx, 1.0, -1.0);
    CGContextSetShouldAntialias(ctx, true)


    CGContextSetRGBStrokeColor(ctx, 0.3, 0.3, 0.3, 1)

    if let tree = self.tree {
        drawBranch(tree, context: ctx)
    }

    CGContextStrokePath(ctx)
    CGContextRestoreGState(ctx);
}

是否有任何希望让它变得更快,或者我应该早就放弃并转向其他渲染 method/engine?

我通读了 this question here,这似乎暗示它永远不会起作用,但那是 3 年前的事了,我想知道从那时起是否有任何变化。

您可以改为将路径视为数据,即每当影响树的某些更改(例如添加分支)时,重新计算路径并重绘,这样您只需支付 1 秒的惩罚一次.

基本上,您需要重构 drawBranch 函数,而不是将 绘制到 上下文中,return 一个 CGPath 对象。然后可以将其保留在视图中并在 drawRect: 方法中重新绘制。

另一种选择是使用 CATiledLayer,但前提是您能够一次只绘制部分视图(例如,您可以将绘图拆分为 100x100 像素的图块)。这不一定会使速度更快,但可以避免绘制树中当前不可见的部分,并且只在需要时才绘制它们。

简而言之,尝试将确定树(模型)路径的逻辑与表示(将其绘制到CGContext中)分开。生成树路径完全有可能是一项昂贵的操作,但至少通过将其与绘图分开,您可以避免阻塞主线程,并确保尽可能少地完成耗时的计算。