【问题标题】:NSScrollView calls drawRect on custom views for every frameNSScrollView 在每一帧的自定义视图上调用 drawRect
【发布时间】:2014-04-23 16:58:13
【问题描述】:

我在 iOS 方面有很多经验,但我是 MacOS 开发的新手。

我正在使用 NSScrollView 滚动 NSView 的自定义子类的多个实例。这个自定义子类有一个自定义的drawRect 实现。所以这个子类的多个实例会同时显示(甚至可以是多达 100 个实例)。

一切正常,但是当我滚动时,我发现它做得不是很顺利。通过在drawRect 实现中放置NSLog() 语句,我很快发现在滚动过程中为每一帧调用它。

我在 iOS 上习惯的是 drawRect 被调用一次,并且内容永远不会重绘,除非你通过调用 setNeedsDisplay 来请求它。

我想通过在滚动期间不让我的自定义 NSView 重绘很多次来提高我的 NSScrollView 的性能,而是记住上次绘制的内容。怎么办?

【问题讨论】:

  • 即使不滚动也会调用drawRect吗?这似乎很正常(至少对我而言)我的 NSScrollViews 也是如此。将所有 CPU 密集型代码移出 drawRect 并让它绘制其内容可能会有所帮助。

标签: objective-c macos nsscrollview


【解决方案1】:

我想出了一个方法让它只画一次!我现在使用NSImage 一次绘制所有内容。我只在模型更改时再次这样做。

buffer = [[NSImage alloc] initWithSize:self.bounds.size];
[buffer lockFocus];
[self drawStuff];
[buffer unlockFocus];

之后,我只是将该图像绘制到屏幕上,这似乎方式更快。

- (void) drawRect:(NSRect) dirtyRect {
    [buffer drawInRect:self.bounds];
}

【讨论】:

  • 我最初考虑过这个。我假设你没有交互性?
  • 使用 NSImage 时如何调整大小?遇到问题?
  • 我刚刚测量了它的速度有多快。正常绘制平均耗时 0276 毫秒,而绘制图像平均耗时 0096 毫秒。
  • 我现在没有互动,但我以后会有。我认为这不会引起问题,因为每次我需要更改绘图时,我都可以简单地更新缓冲区图像。至于调整大小......它可能会导致问题。我目前正在 NSPopover 中呈现所有这些,所以我不容易检查调整大小的行为。
  • 我认为调整大小可以实现- (void) resizeSubviewsWithOldSize:(NSSize) oldSize 来更新图像缓冲区。
【解决方案2】:

如果您的 drawRect 性能非常密集,设置 [scrollView.contentView setCopiesOnScroll:YES];“可能”会有所帮助。

【讨论】:

  • 感谢您的建议!不幸的是,设置该属性没有效果:( drawRect 仍然经常被调用。
  • 您是否分析了您的drawRect 电话?如果花费的时间超过几毫秒,您就是在做一些不必要的事情。
  • 我刚做了。每个 NSView 的渲染时间不到 1 毫秒。问题是这个 NSView 有 40 个实例同时可见。
  • 我在 NSScrollView 的documentView 中遇到了 NSTextViews 的上限。我最终将它们全部呈现在 documentView 的 drawRect 中,显着减少了开销。
  • 你是如何一次渲染它们的?直接调用所有drawRect?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多