如何使用NSView的prepareContentInRect控制scrollview overdraw?

时间:2015-03-23 15:23:40

标签: nsview appkit nsscrollview nsclipview

我试图更好地理解它的用法,以提高OSX的滚动性能。更具体地说,我试图消除屏幕一侧的“闪烁/闪烁”,因为你快速滚动,AppKit运行到视图的非透支(未准备)部分或视图中已准备不正确的部分仅限背景。

我的理解是preparedContentRect表示滚动视图的透支部分 - 可用于响应式滚动的区域。

第一部分

我将preparedContentInRect中的代码放在NSScrollView的两个子视图中 - 每个子视图都是NSScrollView的浮动子视图,其滚动时的行为与documentViews相同。

在程序启动后(正如预期的那样)会多次调用preparedContentInRect。然后我滚动到预备区域的末端但是(意外地)它不再被调用,因为我越来越近,甚至在准备区域的边缘。为什么不?即使没有用户与UI的交互(系统空闲),它也不会调用preparedContentInRect来动态扩大过度绘制区域。

第二部分

因为(如上所述)我不能依赖AppKit在需要时调用preparedContentInRect;我重新组织了我的代码,以便在剪辑视图preparedContentRect的每个通知之后准备boundsChangeNotification,然后手动调用prepareContentInRect以通知AppKit新的透支区域。

我已经包含了一个“手动”标记,以便我的自定义覆盖可以区分我对prepareContentInRect的手动调用和来自AppKit的内部调用 - 以免让AppKit搞砸了透支!

var manuallyPrepareContentInRect = false
override func prepareContentInRect(rect: NSRect) {
    if manuallyPrepareContentInRect{
        println("GRID manual prepareContentInRect call: \(rect)")
        manuallyPrepareContentInRect = false
        super.prepareContentInRect(rect)
        return
    }
    println("GRID bypass AppKit prepareContentInRect call: \(self.preparedContentRect)")
    super.prepareContentInRect(self.preparedContentRect)
}

不幸的是,即使prepareContentRect正在报告我的预定准备矩形,当它滚动它似乎没有按照我的意图准备矩形 - 它准备了一个3,500宽的矩形而不是5,040宽,因此我在等待视图的其余部分渲染时,遇到可怕的背景颜色。

关于未获得正确透支的视图的唯一“特殊”事情是,它使用canDrawSubviewsIntoLayer将大量子视图绘制到其图层中。

对于prepareContentInRect和透支,我上面有什么误解?为什么AppKit的表现如此?

0 个答案:

没有答案