Macos 如何优化Cocoa绘图以确保平滑滚动
我使用标准的Cocoa绘图API在NSView上绘制图形。见下图。在滚动视图中的NSView上有多个图形。每个图形都有大约1440个数据点,由于正在进行重绘,所以滚动性能有点困难 有没有办法确保图形只绘制一次,以便图像可以平滑地上下滚动 该视图用于生成PDF输出文件 如果图形实际上不需要更改,除非调整视图的大小,而且这种情况不会发生,那么是否有任何方法可以防止视图在滚动期间重新绘制自身。希望有一个简单的开关,以确保视图绘制自己一次,并保持在内存中 基本代码在NSView子类draw()函数中Macos 如何优化Cocoa绘图以确保平滑滚动,macos,cocoa,draw,nsview,Macos,Cocoa,Draw,Nsview,我使用标准的Cocoa绘图API在NSView上绘制图形。见下图。在滚动视图中的NSView上有多个图形。每个图形都有大约1440个数据点,由于正在进行重绘,所以滚动性能有点困难 有没有办法确保图形只绘制一次,以便图像可以平滑地上下滚动 该视图用于生成PDF输出文件 如果图形实际上不需要更改,除非调整视图的大小,而且这种情况不会发生,那么是否有任何方法可以防止视图在滚动期间重新绘制自身。希望有一个简单的开关,以确保视图绘制自己一次,并保持在内存中 基本代码在NSView子类draw()函数中 o
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)
}
}
}
苹果在他们的文章中提供了相当全面的建议 看起来你甚至没有采取最小的步骤来避免画你不需要的东西。例如,您显示的代码不会检查
dirtyRect
,以查看给定的绘图是否完全超出它的范围,因此不需要绘制
但是,正如那篇文章中所描述的,使用getrectsbeingdraw(\uquot:)
和/或needsToDraw(\uquot:)
方法通常可以做得更好
在某些情况下,滚动视图可以保存已经绘制的内容,这样视图就不需要重新绘制。看。不过,其中的一个要求是,您的视图需要不透明。它需要覆盖isOpaque
以返回true。不过,仅仅声称自己不透明是不够的。您的视图实际上必须是不透明的,每次调用draw()
时都要绘制整个脏矩形。在进行其他绘图之前,可以使用背景色填充脏矩形以满足此要求
确保剪辑视图的copiesOnScroll
属性也设置为true。这可以在IB中完成(尽管它是作为滚动视图的属性显示的),也可以在代码中完成。默认情况下,它应该为true
请注意,作为响应滚动的一部分的透支将在空闲时间内增量发生。这将涉及重复调用视图的
draw()
方法。如果您没有优化它,只绘制与脏rect相交的东西,那么这些调用将非常缓慢/昂贵。所以,一定要进行优化。苹果在他们的文章中提供了非常全面的建议
看起来你甚至没有采取最小的步骤来避免画你不需要的东西。例如,您显示的代码不会检查dirtyRect
,以查看给定的绘图是否完全超出它的范围,因此不需要绘制
但是,正如那篇文章中所描述的,使用getrectsbeingdraw(\uquot:)
和/或needsToDraw(\uquot:)
方法通常可以做得更好
在某些情况下,滚动视图可以保存已经绘制的内容,这样视图就不需要重新绘制。看。不过,其中的一个要求是,您的视图需要不透明。它需要覆盖isOpaque
以返回true。不过,仅仅声称自己不透明是不够的。您的视图实际上必须是不透明的,每次调用draw()
时都要绘制整个脏矩形。在进行其他绘图之前,可以使用背景色填充脏矩形以满足此要求
确保剪辑视图的copiesOnScroll
属性也设置为true。这可以在IB中完成(尽管它是作为滚动视图的属性显示的),也可以在代码中完成。默认情况下,它应该为true
请注意,作为响应滚动的一部分的透支将在空闲时间内增量发生。这将涉及重复调用视图的
draw()
方法。如果您没有优化它,只绘制与脏rect相交的东西,那么这些调用将非常缓慢/昂贵。所以,一定要进行优化。好的建议。您还可以查看方法bitmapImageRepForCachingDisplayInRect:
和cacheDisplayInRect:toBitmapImageRep:
。对于这种特殊情况,可能没有必要,但谁知道呢。谢谢,只创建一次所有“NSBezierPath”是否有意义,即将它们存储在一个数组中,然后在该数组上迭代以检查每个路径是否与脏矩形相交,如果是,则调用路径“stroke()”方法?好的建议。您还可以查看方法bitmapImageRepForCachingDisplayInRect:
和cacheDisplayInRect:toBitmapImageRep:
。对于这种特殊情况可能没有必要,但谁知道呢。谢谢,只创建一次所有“NSBezierPath”是否有意义,即将它们存储在一个数组中,然后在该数组上迭代以检查每个路径是否与脏rect相交,如果是,则调用路径“stroke()”方法?