如何优化Cocoa绘图以确保平滑滚动

时间:2016-12-22 23:10:53

标签: macos cocoa draw nsview

我使用标准的Cocoa绘图API在NSView上绘制图形。见下图。 NSView上有多个图形,位于scrollView中。由于正在进行重绘,每个图表有大约1440个数据点,滚动性能有点挣扎。

有没有办法确保只绘制一次图形,使图像可以平滑地上下滚动?

此视图用于生成PDF输出文件。

鉴于绘图实际上不需要更改,除非视图已调整大小,并且这不会发生,是否有任何方法可以阻止视图在滚动期间重绘自身。希望有一个简单的开关来确保视图自己绘制一次并将其保留在内存中!?

基本代码在NSView子类draw()函数中。

override func draw(_ dirtyRect: NSRect) {

    drawAxis()

    // Only draw the graph axis during live resize
    if self.inLiveResize {
        return
    }

    plot1()
    plot2()
    plot3()
    ...

 }

 func plot1(){

     for value in plot1Data {

        path = NSBezierPath()

        if isFirst {
           path?.move(to: value)
        } else {
           path?.line(to: value)
        }
     }
 }

enter image description here

1 个答案:

答案 0 :(得分:3)

Apple在View Programming Guide: Optimizing View Drawing文章中提供了非常全面的建议。

您似乎并没有采取最小的步骤来避免画出您不必要的东西。例如,您显示的代码不会检查dirtyRect以查看给定的情节是否完全在其之外,因此不需要绘制。

如该文章所述,您通常可以使用getRectsBeingDrawn(_:count:)和/或needsToDraw(_:)方法做得更好。

在某些情况下,滚动视图可以保存已经绘制的内容,因此您的视图不需要重绘。请参阅release notes for Responsive Scrolling。但是,这方面的一个要求是您的视图需要不透明。它需要覆盖isOpaque才能返回true。但是,仅仅声明是不透明的还不够。通过在每次调用draw()时绘制整个脏矩形,您的视图实际上必须是不透明的。在进行其他绘图之前,您可以使用背景颜色填充脏矩形以满足此要求。

确保剪辑视图的copiesOnScroll属性也设置为true。这可以在IB中完成(尽管它在那里作为滚动视图的属性呈现)或在代码中完成。它应该是默认的。

请注意,响应滚动的过度绘制将在空闲时间内逐步发生。这将涉及重复调用您观看的draw()方法。如果你没有优化它只绘制与脏矩形相交的东西,那么这些调用将变得缓慢/昂贵。所以,请务必进行优化。